package greenfoot;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.util.AbstractSet;
import java.util.Iterator;
| This is an ordered set.
|
| @author Davin McCall
|
public class ActorSet extends AbstractSet<Actor>{
private ListNode listHeadTail = new ListNode();
private ListNode [] hashMap = new ListNode[0];
private int numActors = 0;
| Sum of sequence numbers of contained actors
|
private int myHashCode = 0;
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public int hashCode()
{
return myHashCode;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public boolean add(Actor actor)
{
if (containsActor(actor)) {
return false;
}
numActors++;
ListNode newNode = new ListNode(actor, listHeadTail.prev);
int seq = ActorVisitor.getSequenceNumber(actor);
if (numActors >= 2 * hashMap.length) {
resizeHashmap();
}
else {
int hash = seq % hashMap.length;
ListNode hashHead = hashMap[hash];
hashMap[hash] = newNode;
newNode.setHashListHead(hashHead);
}
myHashCode += seq;
return true;
}
private void resizeHashmap()
{
hashMap = new ListNode[numActors];
ListNode currentActor = listHeadTail.next;
while (currentActor != listHeadTail){
int seq = ActorVisitor.getSequenceNumber(currentActor.actor);
int hash = seq % numActors;
ListNode hashHead = hashMap[hash];
hashMap[hash] = currentActor;
currentActor.setHashListHead(hashHead);
currentActor = currentActor.next;
}
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
public boolean containsActor(Actor actor)
{
return getActorNode(actor) != null;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public boolean contains(Object o)
{
if (o instanceof Actor) {
Actor a = (Actor) o;
return containsActor(a);
}
return false;
}
| Get the list node for an actor (null if the actor is not in the set).
|
private ListNode getActorNode(Actor actor)
{
if (hashMap.length == 0) {
return null;
}
int seq = ActorVisitor.getSequenceNumber(actor);
int hash = seq % hashMap.length;
ListNode hashHead = hashMap[hash];
if (hashHead == null) {
return null;
}
else if (hashHead.actor == actor) {
return hashHead;
}
ListNode curNode = hashHead.nextHash;
while (curNode != hashHead){
if (curNode.actor == actor) {
return curNode;
}
curNode = curNode.nextHash;
}
return null;
}
public boolean remove(Actor actor)
{
ListNode actorNode = getActorNode(actor);
if (actorNode != null) {
remove(actorNode);
myHashCode -= ActorVisitor.getSequenceNumber(actor);
return true;
}
else {
return false;
}
}
private void remove(ListNode actorNode)
{
int seq = ActorVisitor.getSequenceNumber(actorNode.actor);
int hash = seq % hashMap.length;
if (hashMap[hash] == actorNode) {
hashMap[hash] = actorNode.nextHash;
if (hashMap[hash] == actorNode) {
hashMap[hash] = null;
}
}
actorNode.remove();
numActors--;
if (numActors <= hashMap.length / 2) {
resizeHashmap();
}
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public int size()
{
return numActors;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public Iterator iterator()
{
return new ActorSetIterator();
}
@OnThread(Tag.Simulation)
private class ListNode
{
Actor actor;
ListNode next;
ListNode prev;
ListNode nextHash;
ListNode prevHash;
public ListNode()
{
next = this;
prev = this;
}
| Create a new list node and insert it at the tail of the list.
| @param actor
| @param listTail
|
public ListNode(Actor actor, ListNode listTail)
{
this.actor = actor;
next = listTail.next;
prev = listTail;
listTail.next = this;
next.prev = this;
}
| Set this node as the new head node in a hash bucket list.
| @param oldHead The original head node in the bucket
|
public void setHashListHead(ListNode oldHead)
{
if (oldHead == null) {
nextHash = this;
prevHash = this;
}
else {
nextHash = oldHead;
prevHash = oldHead.prevHash;
oldHead.prevHash = this;
prevHash.nextHash = this;
}
}
public void remove()
{
next.prev = prev;
prev.next = next;
nextHash.prevHash = prevHash;
prevHash.nextHash = nextHash;
}
}
@OnThread(Tag.Simulation)
private class ActorSetIterator implements Iterator<Actor>
{
ListNode currentNode;
public ActorSetIterator()
{
currentNode = listHeadTail;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public boolean hasNext()
{
return currentNode.next != listHeadTail;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public Actor next()
{
currentNode = currentNode.next;
return currentNode.actor;
}
@OnThread(value = Tag.Simulation, ignoreParent = true)
@Override
public void remove()
{
ActorSet.this.remove(currentNode);
}
}
}
. hashCode
. add
. resizeHashmap
. containsActor
. contains
. getActorNode
. remove
. remove
. size
. iterator
top,
use,
map,
class ListNode
. ListNode
. ListNode
. setHashListHead
. remove
. ActorSetIterator
. hasNext
. next
. remove
347 neLoCode
+ 9 LoComm