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

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)");
}
}

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.

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

Double Linked List

//I have a single linked list that looks like this
node head = new Node ();
head.info = 3;
head.next = new Node ();
head.next.info = 6 ();
head.next.next = new Node ();
head.next.next.info = 9;
head.next.next.next = null;
//How would I write a double linked list?
class Double Node
{
info;
doubleNode prev;
doubleNode next;
}
Here is the part for creating a double linked list and adding nodes to it.
You can update it by adding remove and insert functions as you want.
class Node{
Node prev;
Node next;
int value;
public Node(int value) {
this.value = value;
}
}
class DoubleLinkedList{
Node head;
Node tail;
public DoubleLinkedList(Node head) {
this.head = head;
this.tail = head;
head.next = null;
head.prev = null;
}
public void addNode(Node node){
tail.next = node;
node.prev = tail;
tail = node;
}
}
public class Main {
public static void main(String args[]){
Node head= new Node(3);
DoubleLinkedList list = new DoubleLinkedList(head);
list.addNode(new Node(5));
list.addNode(new Node(6));
list.addNode(new Node(7));
list.addNode(new Node(8));
}
}
This would be the idea:
node head = new Node();
head.info = 3;
node prev, actual, next;
prev = head;
actual.prev = prev;
actual.info = 6;
actual = actual.next = new Node();
actual.prev = prev;
actual = actual.next = new Node();
actual.info = 9;
...
Assuming that you will have the behavior in your example, you can automate it with a function, in c# would be something like:
function GetDoubleLinkedList(Node head, int from, int end, int jumps)
{
head.info = from;
node prev = head, actual, next;
for(var i = from+jumps; i <= end; i+=jumps)
{
actual.prev = prev;
actual.info = i;
actual = actual.next = new Node();
}
actual.info = end;
return head;
}
//...
//then you can do
node head = new Node();
head = GetDoubleLinkedList(head, 3, 9, 3);
//...
Double linked list are like single linked list with the exception that they have two pointer in the declaration of structure
a previous pointer and a next pointer
For sample implementation see this link
Here is an implementation of a DoubleLinkedList in Java (along with some examples that might help you understand how it's working):
public class Node {
public int value;
public Node prev;
public Node next;
public Node(int value) {
this.value = value;
this.prev = null;
}
public Node(int value, Node prev) {
this.value = value;
this.prev = prev;
}
public Node add(int value) {
if(this.next == null) {
this.next = new Node(value, this);
} else {
this.next.add(value);
}
return this;
}
public Node last() {
if(this.next == null) {
return this;
} else {
return this.next.last();
}
}
public String toString() {
String out = value+" ";
if(this.next != null) {
out += this.next.toString();
}
return out;
}
public static void main(String...arg) {
Node list = (new Node(3)).add(6).add(5).add(9);
System.out.println(list.toString());
//Output:3 6 5 9
System.out.println(list.last().toString());
//Output:9
System.out.println(list.last().prev.prev.toString());
//Output:6 5 9
}
}
You can use following DoubleLinkedList class.
public class DoubleLinkedList<T>
{
Node<T> start;
Node<T> end;
public void AddFirst(T dataToAdd)
{
Node<T> tmp = new Node<T>(dataToAdd);
if (start == null)
{
start = tmp;
end = start;
return;
}
start.previous = tmp;
tmp.next = start;
start = tmp;
if (start.next == null)
{
end = start;
}
}
public void AddLast(T dataToAdd)
{
if (start == null)
{
AddFirst(dataToAdd);
return;
}
Node<T> tmp = new Node<T>(dataToAdd);
end.next = tmp;
tmp.previous = end;
end = tmp;
}
public T RemoveFirst()
{
if (start == null) return default(T);
T saveVal = start.data;
start = start.next;
start.previous = null;
if (start == null) end = null;
return saveVal;
}
public T RemoveLast()
{
if (start == null) return default(T);
T saveVal = end.data;
end = end.previous;
end.next = null;
if (start == null) end = null;
return saveVal;
}
public void PrintAll()
{
Node<T> tmp = start;
while (tmp != null)
{
Console.WriteLine(tmp.data.ToString());
tmp = tmp.next;
}
}
}
And Use the following Node class
class Node<T>
{
public T data;
public Node<T> next;
public Node<T> previous;
public Node(T newData)
{
data = newData;
next = null;
previous = null;
}
}

Linked List and Double Linked List?

I have been given a university assignment to adjust a single linked list to create a double linked list.
I am having trouble understanding a part of the code.
The bit I am having problems with is the method "insert(object o, int index)"
My problem is related to:
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
I dont understand how it knows what nodePointer.next is in the line "nodePointer = nodePointer.next;
I cant see any point where it defines how to handle the .next bit.
How does it know what this is?
I do undestand that it is referencing the next node, but am not clear exactly what this line is saying
The whole code is posted below
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
/**
* <dl>
* <dt>Purpose: Implementation of Sequence ADT.
* <dd>
*
* <dt>Description:
* <dd>This class is an implementation of the Sequence using an linked list as
* the underlying data structure. The capacity is therefore unlimited and
* overflow does not need to be checked.
* </dl>
*
* #author Danny Alexander
* #version $Date: 2000/01/08
*/
public class SequenceList {
/**
* Member class Node encapsulates the nodes of the linked list in
* which the stack is stored. Each node contains a data item and a
* reference to another node - the next in the linked list.
*/
protected class Node {
public Node(Object o) {
this(o, null);
}
public Node(Object o, Node n) {
datum = o;
next = n;
}
//The Node data structure consists of two object references.
//One for the datum contained in the node and the other for
//the next node in the list.
protected Object datum;
protected Node next;
}
//We use object references to the head and tail of the list (the head
//and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
//Only require a single constructor, which sets both object
//references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList() {
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
if (index == 0) {
listHead = new Node(o, listHead);
listTail = listHead;
} else {
throw new SequenceListException("Indexed element is out of range");
}
}
//There is another special case for insertion at the head of
//the sequence.
else if (index == 0) {
listHead = new Node(o, listHead);
}
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
//Finally we need to check that the tail pointer is
//correct. Another special case occurs if the new
//node was inserted at the end, in which case, we need
//to update the tail pointer.
if (nodePointer == listTail) {
listTail = listTail.next;
}
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we just unlink the first node of the
//list.
else {
listHead = listHead.next;
}
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we need to chain all the way down the
//list in order to reset the link of the second to last
//element to null.
else {
Node nodePointer = listHead;
while (nodePointer.next != listTail) {
nodePointer = nodePointer.next;
}
//Unlink the last node and reset the tail pointer.
nodePointer.next = null;
listTail = nodePointer;
}
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
if (index == 0) {
listHead = null;
listTail = null;
} else {
throw new SequenceListException("Indexed element is out of range.");
}
}
//There is also a special case when the first element has to
//be removed.
else if (index == 0) {
deleteFirst();
}
//In the general case, we need to chain down the list to find
//the node in the indexed position.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Unlink the node and reset the tail pointer if that
//node was the last one.
if (nodePointer.next == listTail) {
listTail = nodePointer;
}
nodePointer.next = nodePointer.next.next;
}
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException {
if (listHead != null) {
return listHead.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException {
if (listTail != null) {
return listTail.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//We need to chain down the list until we reach the indexed
//position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
} else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty() {
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size() {
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while (nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear() {
listHead = null;
listTail = null;
}
}
The code you posted lays out several different methods for making insertions into the linked-list.
protected class Node {
public Node(Object o) {
this(o, null);
}
public Node(Object o, Node n) {
datum = o;
next = n; // when creating a Node you have a next attribute associated with each one
}
If this were a double linked list there would be a prev attribute also associated with every Node object. I believe you're saying you are clear on this part.
When just starting out constructing the linked-list, there are two Nodes here that are added by default:
public SequenceList() {
listHead = null;
listTail = null;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
This is the starting point that is needed, so when one of the insert methods are called:
public void insertLast(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
Here you are going to pass insertLast a Node object. If this Node isn't Null in this method, it will create a new tail by adding the new Node as listTail's next member. Then assigning listTails next as the new "Tail".
In this way you're keeping track of the head and the tail. Everytime a new Node is wanted to be added, it becomes the new tail.
You could then go through your list by passing in your head and in either a while-loop or a recursive function that keeps calling on the Nodes next attribute referencing the next item in the list, until you come to Null or you find what it is you were looking for.

Limited ListField items are drawn instead of complete list in Blackberry

I am trying to draw a list of all contacts saved in device. Everything is fine but when I select all contacts, I get only those contacts which are drawn on the screen. In other words, list drawing only those contacts which are visible on screen. To get the remaining contacts I have to scroll the list.
Here is my code:
public class CheckboxListField extends VerticalFieldManager implements ListFieldCallback, FieldChangeListener {
private static Vector selectedContacts ;
private ChecklistData[] mListData = new ChecklistData[] {};
private ListField mListField;
private static Vector mContacts;
private ContactList contactList;
private Enumeration allContacts;
private SendEmail sendEmail;
private boolean isChecked=false;
private BlackBerryContact contactItem;
private VerticalFieldManager _mainVFM = new VerticalFieldManager();
private int i;
private int j=0;
private String emails="";
private ButtonField _inviteButton;
private HorizontalFieldManager selectAllHFM;
private CustomButtonField selectAllButton;
private Bitmap _uncheckBmp;
private Bitmap _checkBmp;
private LabelField selectAllLabel;
private CheckboxField selectAllCheckBox;
private VerticalFieldManager contactListVFM;
private boolean listItemChecked=false;
private StringBuffer rowString;
private boolean getCBoxStatus;
// A class to hold the Strings in the CheckBox and it's checkbox state
// (checked or unchecked).
private class ChecklistData {
private String _stringVal;
private boolean _checked;
private String _telNumber;
ChecklistData(String stringVal, boolean checked) {
_stringVal = stringVal;
_checked = checked;
//_telNumber = telNumber;
}
// Get/set methods.
private String getStringVal() {
return _stringVal;
}
private boolean isChecked() {
return _checked;
}
// Toggle the checked status.
public void toggleChecked() {
_checked = !_checked;
}
}
public CheckboxListField() {
_mainVFM.add(createContactList(isChecked));
add(_mainVFM);
}
public VerticalFieldManager createContactList(boolean checked){
isChecked = checked;
selectedContacts = new Vector();
//INVITE BUTTON
contactListVFM = new VerticalFieldManager();
_inviteButton=new ButtonField("Invite Friend");
_inviteButton.setChangeListener(this);
_inviteButton.setMargin(2,0,10,0);
//SELECT ALL CHECKBOX
selectAllHFM = new HorizontalFieldManager();
_uncheckBmp = Bitmap.getBitmapResource("Uncheck.png");
_checkBmp = Bitmap.getBitmapResource("checked.png");
selectAllButton = new CustomButtonField(29, "", _uncheckBmp, _checkBmp, ButtonField.CONSUME_CLICK);
selectAllButton.setChangeListener(this);
selectAllButton.setMargin(5,5,5,5);
selectAllCheckBox = new CheckboxField("Select All", isChecked){
protected boolean navigationClick(int status,
int time) {
selectedContacts = new Vector();
emails = "";
boolean getCBoxStatus = selectAllCheckBox.getChecked();
if(listItemChecked == false){
if(_mainVFM.getFieldCount()!= 0){
_mainVFM.deleteAll();
_mainVFM.add(createContactList(getCBoxStatus));
}
}
return true;
}
};
selectAllCheckBox.setChangeListener(this);
selectAllLabel = new LabelField("Select All");
selectAllLabel.setMargin(5,5,5,5);
selectAllHFM.add(selectAllCheckBox);
//selectAllHFM.add(selectAllLabel);
// toggle list field item on navigation click
mListField = new ListField() {
protected boolean navigationClick(int status,
int time) {
toggleItem();
return true;
};
};
// set two line row height
//mListField.setRowHeight(getFont().getHeight() * 2);
mListField.setCallback(this);
//contactListVFM.add(new NullField(NullField.FOCUSABLE));
contactListVFM.add(_inviteButton);
contactListVFM.add(selectAllHFM);
contactListVFM.add(new SeparatorField());
contactListVFM.add(mListField);
//LOAD CONTACTS
// load contacts in separate thread
loadContacts.run();
return contactListVFM;
}
protected Runnable loadContacts = new Runnable() {
public void run() {
reloadContactList();
// fill list field control in UI event thread
UiApplication.getUiApplication().invokeLater(
fillList);
}
};
protected Runnable fillList = new Runnable() {
public void run() {
int size = mContacts.size();
mListData = new ChecklistData[size];
for (int i =0; i < mContacts.size() ; i++) {
contactItem = (BlackBerryContact) mContacts
.elementAt(i);
String displayName = getDisplayName(contactItem);
// String telContact = getContact(item);
mListData[i] = new ChecklistData(
displayName, isChecked);
mListField.invalidate(i);
System.out.println(">>>>>>>>>"+mListData[i]);
}
mListField.setSize(size);
//invalidate();
}
};
protected void toggleItem() {
listItemChecked = true ;
selectAllCheckBox.setChecked(false);
listItemChecked =false ;
// Get the index of the selected row.
int index = mListField.getSelectedIndex();
System.out.println("..............."+index);
if (index != -1) {
// Get the ChecklistData for this row.
ChecklistData data = mListData[index];
// Toggle its status.
data.toggleChecked();
mListField.invalidate(index);
}
}
private boolean reloadContactList() {
try {
contactList = (ContactList) PIM
.getInstance()
.openPIMList(PIM.CONTACT_LIST,
PIM.READ_ONLY);
allContacts = contactList.items();
mContacts = enumToVector(allContacts);
mListField.setSize(mContacts.size());
System.out.println(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>>>>>>>>>>"+mListField.getSize());
return true;
} catch (PIMException e) {
return false;
}
}
// Convert the list of contacts from an Enumeration to a Vector
private Vector enumToVector(Enumeration contactEnum) {
Vector v = new Vector();
if (contactEnum == null)
return v;
while (contactEnum.hasMoreElements()){
Contact contact = (Contact) allContacts.nextElement();
if(contactList.isSupportedField(Contact.EMAIL)&& (contact.countValues(Contact.EMAIL) > 0)) {
String emailID=contact.getString(Contact.EMAIL, 0);
if(emailID.length() !=0 && emailID != null ){
v.addElement(contact);
}
}
}
return v;
}
public void drawListRow(ListField list,
Graphics graphics, int index, int y, int w) {
rowString = new StringBuffer();
Object obj = this.get(list, index);
if (list.getSelectedIndex() != index) {
graphics.setBackgroundColor(index % 2 == 0 ||index==0 ? Color.WHITE
: Color.LIGHTGRAY);
graphics.clear();
//list.setFocus();
}
BlackBerryContact contact = (BlackBerryContact) mContacts
.elementAt(index);
String email= contact.getString(Contact.EMAIL, 0);
int vecIndex = selectedContacts.indexOf(email);
if (obj != null) {
ChecklistData currentRow = (ChecklistData) obj;
if (currentRow.isChecked()) {
if(vecIndex == -1){
selectedContacts.addElement(email);
}
rowString
.append(Characters.BALLOT_BOX_WITH_CHECK);
} else {
selectedContacts.removeElement(email);
rowString.append(Characters.BALLOT_BOX);
}
// Append a couple spaces and the row's text.
rowString.append(Characters.SPACE);
rowString.append(Characters.SPACE);
rowString.append(currentRow.getStringVal());
// Draw the text.
}
graphics.drawText(rowString.toString(), 0, y,
0, w);
}
public static String getDisplayName(Contact contact) {
if (contact == null) {
return null;
}
String displayName = null;
// First, see if there is a meaningful name set for the contact.
if (contact.countValues(Contact.NAME) > 0) {
final String[] name = contact.getStringArray(
Contact.NAME, 0);
final String firstName = name[Contact.NAME_GIVEN];
final String lastName = name[Contact.NAME_FAMILY];
if (firstName != null && lastName != null) {
displayName = firstName + " " + lastName;
} else if (firstName != null) {
displayName = firstName;
} else if (lastName != null) {
displayName = lastName;
}
if (displayName != null) {
final String namePrefix = name[Contact.NAME_PREFIX];
if (namePrefix != null) {
displayName = namePrefix + " "
+ displayName;
}
return displayName;
}
}
return displayName;
}
// Returns the object at the specified index.
public Object get(ListField list, int index) {
Object result = null;
if (mListData.length > index) {
result = mListData[index];
}
System.out.println(",,,,,,,,,,,,,,,,,,,,,,,"+mListData.length);
return result;
}
// Returns the first occurrence of the given String,
// beginning the search at index, and testing for
// equality using the equals method.
public int indexOfList(ListField list, String p, int s) {
return -1;
}
// Returns the screen width so the list uses the entire screen width.
public int getPreferredWidth(ListField list) {
return Graphics.getScreenWidth();
// return Display.getWidth();
}
public void fieldChanged(Field field, int context) {
if(field==_inviteButton){
for(int n=0 ; n<selectedContacts.size() ; n++){
emails= emails + selectedContacts.elementAt(n)+",";
}
//}
String mailBody =": "+Jxa.loginUserName+" invited you on NaijaPings app. Please download NaijaPings Android app from here "+"http://appworld.blackberry.com/webstore/content/77264/?lang=en" ;
sendEmail=new SendEmail(mailBody);
sendEmail.Email(emails,Constant.emailSubject);
emails ="" ;
selectedContacts.removeAllElements();
}else if(field == selectAllCheckBox){
selectedContacts = new Vector();
emails = "";
getCBoxStatus = selectAllCheckBox.getChecked();
//selectedContacts.removeAllElements();
if(listItemChecked == false){
if(_mainVFM.getFieldCount()!= 0){
_mainVFM.deleteAll();
_mainVFM.add(createContactList(getCBoxStatus));
}
}
}
}
}
Here ,in drawListRow() , get() method is called only that many times that is number of contacts are visible on the screen. For remaining contact to add, I have to scroll the list.
In drawListRow() method I am adding those contacts into selectedContacts vector and than using those vector to get contact to send a mail. Contacts will be added only when particular list item will be drawn.
So, how I can get all selected contact without scrolling the list?
This is similar to the problem you had in one of your other recent questions. The problem is that drawListRow() is a callback designed to let you draw the rows that need drawing. It's not meant to do anything else, like assembling a list of contacts to email.
The BlackBerry OS tries to be efficient, so it will only ask you to drawListRow() for the rows that are actually visible to the user (on screen). Anything more would be wasteful.
So, if you want to assemble a list of all selected rows, you should do it somewhere else, not in drawListRow().
It looks to me like you can build a list of all currently selected rows by using this code, wherever you want:
public Vector getSelectedContacts() {
selectedContacts.removeAllElements();
for (int i = 0; i < mListData.length; i++) {
Object obj = mListData[i];
if (obj != null) {
BlackBerryContact contact = (BlackBerryContact) mContacts.elementAt(i);
String email = contact.getString(Contact.EMAIL, 0);
int vecIndex = selectedContacts.indexOf(email);
ChecklistData currentRow = (ChecklistData) obj;
if (currentRow.isChecked()) {
if(vecIndex == -1){
selectedContacts.addElement(email);
}
} else {
// this line is probably not actually needed, since we
// call removeAllElements() at the start of this method
selectedContacts.removeElement(email);
}
}
}
return selectedContacts;
}

Resources