Repast: how to count the total number of agents satisfying the specific condition - agent-based-modeling

Each agent has a private boolean variable "Happy?". how to count the agents with [Happy? = True]?
Is there a direct method available in repast? Or I have iterate through all agents and count them individually?
Update:
I have tried the global scheduling method: https://repast.github.io/docs/RepastReference/RepastReference.html#schedule-global
It's not working when I put below code using the #ScheduledMethods in the ContextBuilder.
grid.moveTo(this_girl, group_x,group_y);
}
}
return context;
}
#ScheduledMethod(start = 1, interval = 1, shuffle=true)
public void step () {
Context<Object> context = ContextUtils.getContext(this);
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int end_count = 0;
System.out.println(end_count);
for (Object o : query.query()) {
if (o instanceof Boy) {
end_count ++;
}
if (o instanceof Girl) {
end_count ++;
}
}
System.out.println(end_count);
if (end_count == 70) {
RunEnvironment.getInstance().endRun();
}
}
}
It's working if I put above code in either boy agent or girl agent actions.
#ScheduledMethod(start = 1, interval = 1,shuffle=true)
public void step() {
relocation();
update_happiness();
endRun();
}
public void endRun( ) {
Context<Object> context = ContextUtils.getContext(this);
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int end_count = 0;
System.out.println(end_count);
for (Object o : query.query()) {
if (o instanceof Boy) {
end_count ++;
}
if (o instanceof Girl) {
end_count ++;
}
}
System.out.println(end_count);
if (end_count == 70) {
RunEnvironment.getInstance().endRun();
}
}

You can use a Query for this -- see the query answer to this question:
Repast: how to get a particular agent set based on the specific conditions?
You could also use the query method in a Context where you pass it a predicate where the predicate returns true if happy.
In both of these cases, you'll need an accessor method for the private boolean happy field -- e.g.
public boolean isHappy() {
return happy;
}
Also in both cases, the queries return an iterable over all the agents where happy is true, rather than a collection where you could take the size to get the count. So, you'll have to iterate through that and increment a counter.
Update:
Your current problem is with the scheduling. You can't easily schedule a method on the ConetextBuilder as its not really part of the model, but rather used to initialize it. The easiest way to schedule what you want is to schedule it explicitly in the ContextBuilder with something like:
RunEnvironment.getInstance().getCurrentSchedule().schedule(ScheduleParameters.createRepeating(1, 1, ScheduleParameters.LAST_PRIORITY), () -> {
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int end_count = 0;
System.out.println(end_count);
for (Object o : query.query()) {
if (o instanceof Boy) {
end_count++;
}
if (o instanceof Girl) {
end_count++;
}
}
System.out.println(end_count);
if (end_count == 70) {
RunEnvironment.getInstance().endRun();
}
});
The LAST_PRIORITY should insure that all the agent behavior will have taken place before the happiness count is polled.

Related

Android MediatorLiveData to combine multiple LiveData results into single LiveData object (In Java)

I am using 2 LiveDatas from separate tables into the repository of my application. I add the two LiveDatas as sources to the CustomMediatorLiveData class which extends MediatorLiveData.
In the onChanged callback of addSource method for each LiveData, I send the values of both the LiveDatas into a method that combines both and returns a single LiveData which is set as the value for the CustomMediatorLiveData object. I am creating an object of this CustomMediatorLiveData in my Repository and passing the two LiveDatas as parameters for the constructor.
This runs and doesn't give any error but it is messing up the data within the LiveData itself.
example: If the date was originally 15th August 2020 then it can be something like 14th August 0001.
CustomMediatorLiveData:
public class CustomMediatorLiveData extends MediatorLiveData<List<Object>> {
private List<Note> notes = Collections.emptyList();
private List<RecurringTask> recurringTasks = Collections.emptyList();
public CustomMediatorLiveData(LiveData<List<Note>> liveNotes, LiveData<List<RecurringTask>> liveRecurringTasks) {
addSource(liveNotes, notes1 -> {
if (notes1 != null) {
this.notes = notes1;
}
setValue(combineData(notes,recurringTasks));
});
addSource(liveRecurringTasks, recurringTasks1 -> {
if (recurringTasks1 != null) {
this.recurringTasks = recurringTasks1;
}
setValue(combineData(notes,recurringTasks));
});
}
// This method adds the 2 lists into one and sorts them based on dates and priority.
private List<Object> combineData(List<Note> notes, List<RecurringTask> recurringTasks) {
List<Object> combinedList = new ArrayList<>();
if (notes != null && !notes.isEmpty())
combinedList.addAll(notes);
if(recurringTasks!=null && !recurringTasks.isEmpty())
combinedList.addAll(recurringTasks);
Collections.sort(combinedList, new Comparator<Object>() {
#Override
public int compare(Object o1, Object o2) {
Date d1, d2;
Note n1 = null, n2 = null;
RecurringTask r1 = null, r2 = null;
if (o1 instanceof Note && o2 instanceof Note) {
int hmm = Boolean.compare(((Note) o2).isPriority(), ((Note) o1).isPriority());
if (hmm != 0)
return hmm;
}
if (o1 instanceof Note) {
d1 = ((Note) o1).getEnd_date();
n1 = ((Note) o1);
} else {
d1 = ((RecurringTask) o1).getEnd_date();
r1 = ((RecurringTask) o1);
}
if (o2 instanceof Note) {
d2 = ((Note) o2).getEnd_date();
n2 = ((Note) o2);
} else {
d2 = ((RecurringTask) o2).getEnd_date();
r2 = ((RecurringTask) o2);
}
if (n1 != null) {
if (r2 != null) {
if (n1.isPriority()) {
return -1;
}
}
}
if (n2 != null) {
if (r1 != null) {
if (n2.isPriority()) {
return 1;
}
}
}
long l1 = d1.getTime() - d2.getTime();
if (l1 > 0) {
return 1;
} else if (l1 < 0) {
return -1;
} else {
return 0;
}
}
});
return combinedList;
}
}
Note Repository class:
public class NoteRepository {
private String DB_NAME = "db_task";
Context context;
private RecurringDao recurringDao;
private LiveData<List<RecurringTask>> upcomingRecurringTasks;
private LiveData<List<Note>> upcomingTasks;
private CustomMediatorLiveData customMediatorLiveData;
private NoteDatabase noteDatabase;
public NoteRepository(Context context) {
noteDatabase = NoteDatabase.getInstance(context);
recurringDao = noteDatabase.recurringDao();
upcomingRecurringTasks = recurringDao.getUpcomingRecurringTask();
upcomingTasks = noteDatabase.daoAccess().fetchUpcomingTasks();
this.context = context;
customMediatorLiveData = new CustomMediatorLiveData(upcomingTasks, upcomingRecurringTasks);
}
public LiveData<List<Object>> getCustomMediatorLiveData() {
return customMediatorLiveData;
}
public LiveData<List<RecurringTask>> getUpcomingRecurringTasks() {
return upcomingRecurringTasks;
}
public LiveData<List<Note>> fetchUpcomingTasks() {
return NoteDatabase.getInstance(context).daoAccess().fetchUpcomingTasks();
}
}
I have tried using the MediatorLiveData object and add the two LiveData sources to it in the repository itself and the same issue persists.
What is the correct way to implement this? How to combine 2 LiveDatas into a single LiveData that can be observed.

Repast Java: scheduling agent and global behaviors in a structural way

I am previously working with Netlogo for years and I am very much getting used to developing the agent-based model based on a set of procedures. An example of supply chain simulation model structure looks like below:
;;the main simulation loop
#ScheduledMethod(start = 1, interval = 1)
public void step() {
place-order-to-suppliers() ;;procedures involving customer agent behaviors (a number of methods)
receive-shipment-from-suppliers() ;;procedures involving both supplier and customer agents and their behaviors (methods)
receive-order-from-customers() ;;procedures involving supplier agent only
ship-order-to-customers() ;;procedures involving supplier agent only
summarize() ;;procedures involving global summary behaviors independent of any agents, as well as local summary behaviors per each type of agents (customer and supplier)
}
The above structure is very useful and intuitive to develop a simulation model. We first cut the simulation world into several key parts (procedures), within which we further develop specific methods related to associated agents and behaviors. The essential part is to establish a higher level procedure (like a package) which could be useful to integrate (pack) the different types of agents and their behaviors/interactions altogether in one place and execute the model in a desired sequential order based on these procedures.
Are there any hints/examples to implement such modular modelling strategy in Repast?
Update:
Below is a simple model I wrote which is about how boy and girl interacts in the party (the full reference can be found https://ccl.northwestern.edu/netlogo/models/Party). Below is the code for Boy Class (the girl is the same so not pasted again).
package party;
import java.util.ArrayList;
import java.util.List;
import repast.simphony.context.Context;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.ScheduledMethod;
import repast.simphony.parameter.Parameters;
import repast.simphony.query.PropertyGreaterThan;
import repast.simphony.query.PropertyEquals;
import repast.simphony.query.Query;
import repast.simphony.random.RandomHelper;
import repast.simphony.space.continuous.ContinuousSpace;
import repast.simphony.space.grid.Grid;
import repast.simphony.space.grid.GridPoint;
import repast.simphony.util.ContextUtils;
public class Boy {
private ContinuousSpace<Object> space;
private Grid<Object> grid;
private boolean happy;
private int id, x, y,tolerance;
private boolean over;
Boy (Grid<Object> grid, int id, int x, int y) {
this.grid = grid;
this.id = id;
this.x = x;
this.y = y;
Parameters p = RunEnvironment.getInstance().getParameters();
int get_tolerance = (Integer) p.getValue("tolerance");
this.tolerance = get_tolerance;
}
// #ScheduledMethod(start = 1, interval = 1,shuffle=true)
// public void step() {
// relocation();
// update_happiness();
// endRun();
//
// }
public void endRun( ) {
Context<Object> context = ContextUtils.getContext(this);
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int end_count = 0;
for (Object o : query.query()) {
if (o instanceof Boy) {
end_count ++;
}
if (o instanceof Girl) {
end_count ++;
}
}
if (end_count == 70) {
RunEnvironment.getInstance().endRun();
}
}
public void update_happiness() {
over = false;
Context<Object> context = ContextUtils.getContext(this);
Parameters p = RunEnvironment.getInstance().getParameters();
int tolerance = (Integer) p.getValue("tolerance");
GridPoint pt = grid.getLocation(this);
int my_x = this.getX();
int boy_count = 0;
int girl_count = 0;
Query<Object> query = new PropertyEquals<Object>(context, "x", my_x);
for (Object o : query.query()) {
if (o instanceof Boy) {
boy_count++;
}
else {
girl_count++;
}
}
int total = boy_count + girl_count;
double ratio = (girl_count / (double)total);
// System.out.println((girl_count / (double)total));
if (ratio <= (tolerance / (double)100)) {
happy = true;
// System.out.println("yes");
}
else {
happy = false;
// System.out.println("no");
}
over = true;
// System.out.println(over);
}
public void relocation() {
if (!happy) {
List<Integer> x_list = new ArrayList<Integer>();
for (int i = 5; i <= 50; i = i + 5) {
x_list.add(i);
}
int index = RandomHelper.nextIntFromTo(0, 9);
int group_x = x_list.get(index);
while(group_x == this.getX()){
index = RandomHelper.nextIntFromTo(0, 9);
group_x = x_list.get(index);
}
int group_y = 35;
while (grid.getObjectAt(group_x,group_y) != null) {
group_y = group_y + 1;
}
this.setX(group_x);
grid.moveTo(this, group_x,group_y);
}
}
public int getTolerance() {
return tolerance;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public int getID() {
return id;
}
public boolean getHappy() {
return happy;
}
public boolean getOver() {
return over;
}
public void setTolerance(int tolerance) {
this.tolerance = tolerance;
}
}
---------------------------------------------------------------------------------
The running of above code can follow the standard Repast Annotated scheduling method. However, since I want do some integration of the different agents and their methods altogether to allow the creation of bigger procedures(methods), I managed to create a Global Scheduler Agent Class to manage this modeling strategy. Below is the code:
package party;
import java.util.ArrayList;
import java.util.List;
import repast.simphony.context.Context;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.ScheduleParameters;
import repast.simphony.engine.schedule.ScheduledMethod;
import repast.simphony.engine.schedule.Schedule;
import repast.simphony.query.PropertyEquals;
import repast.simphony.query.Query;
import repast.simphony.util.ContextUtils;
import repast.simphony.util.collections.IndexedIterable;
public class Global_Scheduler {
#ScheduledMethod(start = 1, interval = 1,shuffle=true)
public void updateHappiness() {
Context<Object> context = ContextUtils.getContext(this);
IndexedIterable<Object> boy_agents = context.getObjects(Boy.class);
IndexedIterable<Object> girl_agents = context.getObjects(Girl.class);
for (Object b: boy_agents) {
((Boy) b).update_happiness();
}
for (Object g: girl_agents) {
((Girl) g).update_happiness();
}
}
#ScheduledMethod(start = 1, interval = 1,shuffle=true)
public void relocate() {
Context<Object> context = ContextUtils.getContext(this);
IndexedIterable<Object> boy_agents = context.getObjects(Boy.class);
IndexedIterable<Object> girl_agents = context.getObjects(Girl.class);
for (Object b: boy_agents) {
((Boy) b).relocation();
}
for (Object g: girl_agents) {
((Girl) g).relocation();
}
}
#ScheduledMethod(start = 1, interval = 1,shuffle=true)
public void summary() {
Context<Object> context = ContextUtils.getContext(this);
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int total_count = 0;
int boy_count = 0;
int girl_count = 0;
for (Object o : query.query()) {
if (o instanceof Boy) {
total_count ++;
boy_count++;
}
if (o instanceof Girl) {
total_count ++;
girl_count++;
}
}
System.out.println("Total happy person: " + total_count);
System.out.println("Total happy boys: " + boy_count);
System.out.println("Total happy girls: " + girl_count);
}
#ScheduledMethod(start = 1, interval = 1,shuffle=true)
public void endRun( ) {
Context<Object> context = ContextUtils.getContext(this);
Query<Object> query = new PropertyEquals<Object>(context, "happy", true);
int end_count = 0;
for (Object o : query.query()) {
if (o instanceof Boy) {
end_count ++;
}
if (o instanceof Girl) {
end_count ++;
}
}
if (end_count == 70) {
RunEnvironment.getInstance().endRun();
}
}
}
The above code using the global scheduler agent to run the model is working fine and the outcome should behave the same. However, I am not sure if the execution of the model really follows the sequence (i.e. update_happiness() -> relocate() -> summary() -> end_run(). I would also like to know if there are better and simpler way to achieve such modeling strategy?
The code example you provided will almost work exactly as-is in a repast model agent - you simply need to change the comment line prefix ;; to // and implement the methods place-order-to-suppliers(), etc in the agent class. The agent behavior structure in a typical ABM follows this exact structure. A general 'step' method that combines the various sub-steps according to the desired order of execution.
There are a number of behavior scheduling approaches outlined in the Repast FAQ: https://repast.github.io/docs/RepastReference/RepastReference.html#_scheduling . Scheduling via annotation as you've provided in the example will repeat the behavior on a regular interval, or at a single time step. You can also schedule dynamically in the model by directly putting an action on the Repast schedule. This type of scheduling is good for event-based behavior, like scheduling a one-time behavior that is triggered by some other event in the model. You can also schedule with #Watch annotations that trigger behaviors based on a set of conditions specified in the annotation.
You can use priorities in your #ScheduledMethod annotations, e.g.,
#ScheduledMethod(start = 1, interval = 1, shuffle=true, priority=1)
where a higher priority will run before a lower priority.

I have no idea why i have error Exception in thread "main" java.lang.NullPointerException

I tried to use reverseBystack, reverseBylink and remove.. but I don't know why when i use these functions, it has error like this.
Exception in thread "main" java.lang.NullPointerException
at LinkedQueue$Node.access$200(LinkedQueue.java:44)
at LinkedQueue.reverseBylink(LinkedQueue.java:185)
at LinkedQueue.main(LinkedQueue.java:238)
void reverseByStack() - This method reverses the order of the items in the linked list (first
becomes last and last becomes first) using a stack data strucenter code hereture`
• void reverseByLinks() - This method also reverses the order of the items in the linked list.
It should not create a new list or use a stack. It should only reverse the order of the nodes by
modifying the next values for each node in the list.
• int remove(Item item) - This method scans the queue for occurrences of item and removes
them from the queue. It returns the number of items deleted from the queue.
these are what i want to make.
enter code here public class LinkedQueue<Item> implements Iterable<Item> {
private int N; // number of elements on queue
private Node first; // beginning of queue
private Node last; // end of queue
// helper linked list class
private class Node {
private Item item;
private Node next;
}
public LinkedQueue() {
first = null;
last = null;
N = 0;
assert check();
}
public boolean isEmpty() {
return first == null;
}
public int size() {
return N;
}
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue
underflow");
return first.item;
}
public void enqueue(Item item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
N++;
assert check();
}
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue
underflow");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null; // to avoid loitering
assert check();
return item;
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
private boolean check() {
if (N == 0) {
if (first != null) return false;
if (last != null) return false;
}
else if (N == 1) {
if (first == null || last == null) return false;
if (first != last) return false;
if (first.next != null) return false;
}
else {
if (first == last) return false;
if (first.next == null) return false;
if (last.next != null) return false;
// check internal consistency of instance variable N
int numberOfNodes = 0;
for (Node x = first; x != null; x = x.next) {
numberOfNodes++;
}
if (numberOfNodes != N) return false;
// check internal consistency of instance variable last
Node lastNode = first;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
if (last != lastNode) return false;
}
return true;
}
void reverseBystack(){
Stack<Item> s = new Stack<>();
Item item;
while (s.isEmpty() != true){
item = dequeue();
s.push(item);
}
while(s.isEmpty() != true){
item = s.pop();
enqueue(item);
}
}
void reverseBylink() {
Node prev = null;
Node current = this.first;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
prev.next = current.next;
}
int remove(Item item){
Node cur = first;
Node prev = last;
while(cur != null) {
if(cur.item.equals(item))
System.out.println(cur.item);
}
cur = cur.next;
prev = cur.next;
return 0;
}
public Iterator<Item> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() { return current != null;
}
public void remove() { throw new
UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
/**
* Unit tests the <tt>LinkedQueue</tt> data type.
*/
public static void main(String[] args) {
LinkedQueue<String> q = new LinkedQueue<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) q.reverseBylink();
else if (!q.isEmpty()) StdOut.print(q.dequeue() + " ");
}
StdOut.println("(" + q.size() + " left on queue)");
}
}

EF modify entity in a function

// Inside an action result
tp = dbContext.tp.Single(x => ...);
foreach (Sample sample in tp.samples)
{
if (sample.SampleStatusId == 1)
changeSamplestatus(sample, 2, now); //change samples to on hold
}
dbContext.SaveChanges();
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
sample.SampleHistory.Add(new SampleHistory
{
OldStatus = sample.SampleStatusId,
NewStatus = sampleStatus,
});
sample.SampleStatusId = sampleStatus;
}
I have an entity (sample) that I would like to change it status.
I am calling a function to do so, but the entity doesn't get modified (but it is creating a new row in history table with the correct FK).
It doesn't throw any errors when SaveChanges is called. It just doesn't modify the entity.
You can try:
//INSIDE AN ACTION RESULT
var tp = dbContext.tp.SingleOrDefault(x => ...);
if (tp != null)
{
foreach (Sample sample in tp.samples)
{
if (sample.SampleStatusId == 1)
changeSamplestatus(sample, 2, DateTime.Now);
}
int flag = dbContext.SaveChanges();
if (flag > 0)
{
// update successful
}
}
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
//sample.SampleHistory.Add(new SampleHistory
//{
// OldStatus = sample.SampleStatusId,
// NewStatus = sampleStatus,
//});
sample.SampleStatusId = sampleStatus;
}
Don't use Single for this case, because it would throw exception if no result was found or there were more than 1 result. Use SingleOrDefault or FirstOrDefault instead.
You can try this . I hope thiw will work . The Idea is to get the history records first in the context and then update the propterties and set state to mofifed . Please try I didnt tested it but it should work.
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
var historyRecordToUpdate = db.SampleHistory.FirstOrDefault(h=>h.id == sampleHistoryId )
if(historyRecordToUpdate !=null )
{
db.Entry(sample).State= EntityState.Modified;
sample.SampleStatusId = sampleStatus;
}
}

Linked List search method

I am practicing build a doubly linked list contains string value.
In find method, I have a NullPointer Exception
here is my code.
package LinkedList;
package LinkedList;
public class LinkedList {
// 노드 클래스
class Node {
String value;
Node prev;
Node next;
Node(String v, Node p, Node s) {
value = v;
prev = p;
next = s;
}
public String getValue() {
return value;
}
public Node getPrev() {
return prev;
}
public Node getNext() {
return next;
}
public void setPrev(Node p) {
prev = p;
}
public void setNext(Node n) {
next = n;
}
}
Node head;
Node tail;
int size = 0;
public LinkedList() {
head = new Node(null, null, null);
tail = new Node(null, head, null);
head.setNext(tail);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public String first() {
if (isEmpty()) {
return null;
}
return head.getNext().getValue();
}
public String last() {
if (isEmpty()) {
return null;
}
return tail.getPrev().getValue();
}
public void addFirst(String value) {
addBetween(value, head, head.getNext());
}
public void addLast(String value) {
addBetween(value, tail.getPrev(), tail);
}
public void addBetween(String v, Node p, Node s) {
Node newNode = new Node(v, p, s);
p.setNext(newNode);
s.setPrev(newNode);
size++;
}
public String remove(Node node) {
Node p = node.getPrev();
Node s = node.getNext();
p.setNext(s);
s.setPrev(p);
size--;
return node.getValue();
}
public String removeFirst() {
if (isEmpty()) {
return null;
}
return remove(head.getNext());
}
public String removeLast() {
if (isEmpty()) {
return null;
}
return remove(tail.getPrev());
}
public void insert(String value) {
Node current = head;
// first
if (isEmpty()) {
addFirst(value);
} else {
// check
while (current.getNext() != tail || current.getValue().compareTo(value) > 0) {
current = current.getNext();
}
// last
if (current.getNext() == tail) {
addLast(value);
} else // between
{
addBetween(value, current.getNext(), current);
}
}
}
/* !!!!!!!!!!!!!! ERORR !!!!!!!!!!!! */
public void find(String value) {
Node current = head.getNext();
while ((current != null) || !(current.getValue().equals(value)))
current = current.getNext();
if (current.getValue().equals(value)) {
System.out.println("found " + value);
} else {
System.out.println("Not found " + value);
}
}
// • Traverse the list forwards and print
// 순회
public void fowardTraverse() {
Node current = head.getNext();
System.out.print(current.getValue());
while (current.getNext() != tail) {
current = current.getNext();
System.out.print(" -> " + current.getValue());
}
}
// • Traverse the list backwards and print
// 뒤로 순회
public void backwardTraverse() {
Node current = tail.getPrev();
System.out.print(current.getValue());
while (current.getPrev() != head) {
current = current.getPrev();
System.out.print(" -> " + current.getValue());
}
}
// • Delete a node from the list
// 지우기
public String delete(String value) {
return value;
}
// • Delete/destroy the list
// 파괴하기
public void destroy() {
}
public static void main(String[] args) {
// TODO Auto-generated method stubs
LinkedList a = new LinkedList();
a.insert("a");
a.insert("b");
a.insert("c");
a.insert("d");
a.insert("e");
a.insert("f");
a.insert("g");
a.insert("h");
a.insert("i");
// a.fowardTraverse();
a.find("a");
}
I don't understand why I get a nullpointException at the line,
It suppose to put a node contains a.
Make sure you check for Non-NULL before dereferencing:
Node current = head.getNext();
and
if (current.getValue().equals(value)) {
to be replaced by
Node current;
if(head != NULL) current = head.getNext();
and
if (current != NULL && current.getValue().equals(value)) {
Because your Head is empty...(No pun intended)
before Addfirst calling..your structure:
head=[null,null,tail],tail=[null,head,null];
you are sending ("a",head,tail)
and your storing it in new node making it a structure like:
head=[null,null,newNode]==>newNode["a",head,tail]==>tail[null,newNode,null]
So search will compare null to a (in find) giving you the error .....
---Edit 1:
#JanghyupLee, My Bad, Didn't do a closer look on find method...however , I found that in condition of "if" you are using condition
current != null || ......
After first line that is ( current=head.next)..current becomes not null..
which is causing the condition in while to ignore the right part of '||' (short circuit) until current has a value of null...
Once the current becomes null then it goes for the next statement to check for value..causing null pointer exception

Resources