Very rudimentary question but I have a loop e.g.
List<ObjectList> = //set of values inside.
for(Object data : ObjectList){
// how to access next element?
// current element is accesed by 'data'. I could get the index position and then increment but is there a easier way?
}
How would you get the next element/previous? I know there are iterators i can use and so on but i want to know a neat way to do it in a for loop.
You can but don't do it as the time complexity of the loop will
increase. Just use a normal loop with an int i looping variable.
If you still want to do it you can find the index this way:
int index = lst.indexOf(data);
Then index+1 is the index of the next element.
And index-1 is the index of the previous element.
Make two methods for next and pervious and pass list and element.
public static <T> T nextElement(List<T> list,T element){
int nextIndex=list.indexOf(element)+1;
return list.size()<nextIndexlist?null:list.get(nextIndex);
}
public static <T> T previousElement(List<T> list,T element){
int previousIndex=list.indexOf(element)-1;
return list.size()>previousIndexlist?null:list.get(previousIndex);
}
1)First way
for(ObjectList data : objectList){
ObjectList previousElement=previousElement(objectList,data);
ObjectList nextElement=nextElement(objectList,data);
}
2) Second way
for(int i=0;i<=objectList.size();i++){
ObjectList previousElement=objectList.size>i-1?null:objectList.get(i-1);
ObjectList nextElement=objectList.size<i+1?null:objectList.get(i+1);
}
3) Third way using iterator
Actually, your for-each isn't iterating a List. This,
List<ObjectList> = //set of values inside.
for(Object data : ObjectList){
}
Should look something like,
List<ObjectList> al = new ArrayList<>();
for(ObjectList data : al){ // <-- like so.
}
But that won't find any data until you populate the List.
Using a "normal" for-loop, this might be, what you are looking for:
List<Object> objectList = new ArrayList<>();
// add some data
for (int i = 0; i < objectList.size(); i++) {
System.out.println((i > 0) ? "previous Object: " + objectList.get(i - 1) : "No previous object, current is the first one.");
System.out.println("Current Object: " + objectList.get(i));
System.out.println((i < objectList.size()) ? "Next Object: " + objectList.get(i + 1) : "No next object, current is the last one.");
}
Key aspect is, that you have to use your loop variable (i in this case) to access your actual elements. i + 1 gives you the next element and i - 1 the previous.
I think what you is an iterator, its used like this:
List<ObjectList> list= //set of values inside.
Iterator<ObjectList> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
System.out.println(iterator.previous());
iterator.next()
}
It allows you to access the next and previous objects.
ListIterator:
There is the ListIterator which can a bit of stepping back and forth.
Mind in the code below previousIndex() yields -1 at the start.
for (ListIterator<Object> iter = objectList.listIterator(); iter.hasNext(); ) {
Object object = iter.next();
Object previous = objectList.get(iter.previousIndex()); // Might fail
Object next = objectList.get(iter.nextIndex()); // Might fail
if (iter.hasPrevious()) ... iter.previous();
}
Related
I want to save the final value on a LinkedList of 5000000 integers by using an iterator. For this assignment, I need to traverse through the entire list (I know this is not the most efficient way). Here is the code that I have:
//method 1:
ListIterator ls = list.listIterator();
while (ls.hasNext()) {
var save = ls.next(); //my attempt to save the final value
ls.next();
}
What is the best way for me to save the value at the last index to a variable?
What is the best way for me to save the value at the last index to a
variable?
Keeping in mind that there are 5.000.000 elements the most efficient way to access the last element is to make use of the fact that LinkedList implements the Deque interface:
List<Integer> list = new LinkedList<>();
.....
Integer last = ((Deque<Integer>) list).peekLast();
Note:
any element in the list could be null and application will crash if you'll try to assign null to an int variable;
in order to invoke the method peekLast() first you have to cast the list to the appropriate type.
But, if for this task you have to use a ListIterator at all costs, then I advise you to fix the code you've provided like that:
public static Optional<Integer> getLast(List<Integer> list) {
ListIterator<Integer> ls = list.listIterator();
Integer last = null;
while (ls.hasNext()) {
last = ls.next();
}
return Optional.ofNullable(last);
}
ListIterator<Integer> ls = list.listIterator();
int last = -1;
while (ls.hasNext()) {
last = ls.next();
}
Alternatively, don't save the value as you go through the list:
while (ls.hasNext()) {
ls.next();
}
// Assuming the list isn't empty:
var last = ls.previous();
You can use
list.getLast();
to get the last item from the list.
I have two for loops written in java below. The first one grabs all the titles of news articles on a website, and the second one grabs all the links of the same new articles on the same website.
How do I make it so that when the first loop executes once, the second loop executes once, and then the first loop executes a second time, and the second one executes a second time, etc. I would really appreciate your help, thanks.
for( org.jsoup.nodes.Element element : elements1 ){
sendMessageRequest.setText(element.text());
sendMessage(sendMessageRequest);
System.out.print("sent message");
}
for( org.jsoup.nodes.Element element : elements2 ) {
sendMessageRequest.setText(element.text());
sendMessage(sendMessageRequest);
System.out.print("sent message");
}
I'm going to assume that elements1 and elements2 are some kind of Iterable<Element>, e.g. List<Element>.
First, remember that for (Element element : elements1) is just syntactic sugar for:
Iterator<Element> iter = elements1.iterator();
while (iter.hasNext()) {
Element element = iter.next();
// code here
}
Except that you don't have access to the Iterator.
So, if you want to iterate two different Iterable objects, do so the old-fashioned way:
Iterator<Element> iter1 = elements1.iterator();
Iterator<Element> iter2 = elements2.iterator();
while (iter1.hasNext() && iter2.hasNext()) {
Element element1 = iter1.next();
Element element2 = iter2.next();
// code here
}
If the two Iterable objects are not the same length, the loop will only iterate until the shorter one has been exhausted. Extra elements in the other one will simply be ignored.
If elements1 and elements2 are guaranteed to have the same length, just iterate through them into one loop:
for (int i = 0; i < elements1.length; i++) {
processMessageRequest(elements1[i]);
processMessageRequest(elements2[i]);
}
Using a new method processMessageRequest to make your code more DRY:
private void processMessageRequest(Element e) {
sendMessageRequest.setText(e.text());
sendMessage(sendMessageRequest);
System.out.println("sent message");
}
I'm not sure what the scope of sendMessageRequest is... but with some tweaking this way could work.
I'm learning to iterate, and have implemented an Iterator on my 'CStickChart' Class using the following private property:
private List<CStick> cStickCollection = new ArrayList<CStick>();
and then implementing the method to return CSticks:
public Iterator<CStick> iterator() {
return this.cStickCollection.iterator();
}
Now when I try and iterate through it, I'm able to do so with the assigned localCStick but calling the next() method on the CStickChart Iterator doesn't do what I expected it to. I expected it to give me the next CStick in my CStickChart (hence when I call the getEPIC I was expecting it to give me the next EPIC along).
// Print the EPIC out of the Array using the iterator
for (CStick localCStick : testCStickChart) {
System.out.println(localCStick.getEPIC());
//The below line doesn't return the next CStick and I'm not sure why
System.out.println("next EPIC is " + testCStickChart.iterator().next().getEPIC());
}
Please could someone explain why this is not the case (it always returns the first EPIC)
System.out.println("next EPIC is " + testCStickChart.iterator().next().getEPIC());
This happens because in this line you are getting a new iterator in every iteration of the loop. Each new iterator starts from the beginning of the list again.
It sounds like you don't want to use the enhanced-for structure. The reason: an enhanced-for with an iterable entity will use the iterator provided internally, and will only ever advance forward.
This also means that any calls to a iterator while inside that loop produce an iterator that starts at the beginning of iteration.
So, with that, you have two options - both of which involve abandoning the enhanced-for:
Use a standard for loop with indexing to advance backwards and forwards with the list, or
Use a ListIterator as provided by List to move backwards and forwards in a very seamless way.
Here is an example with using integers - note that every time I advance the iterator I have to move it back to its previous spot so that I don't double-advance it. Also, I have a condition to break out of the loop once we've run out of elements.
List<Integer> integerList = new ArrayList<Integer>() {{
add(1);
add(2);
add(3);
add(4);
add(5);
add(6);
add(7);
add(8);
add(9);
add(10);
}};
for (ListIterator<Integer> iterator = integerList.listIterator(); iterator.hasNext(); ) {
int value = iterator.next();
int nextValue = Integer.MIN_VALUE;
if (iterator.hasNext()) {
nextValue = iterator.next();
// Reset the state of the iterator
iterator.previous();
}
System.out.println("Value = " + value);
if(nextValue != Integer.MIN_VALUE) {
System.out.println("Next value = " + nextValue);
}
}
Because you are getting the top iterator of cStickCollection with .iterator(). I think you wanted to use the same iterator position as you're at in your loop, and peek at the next element. You can't do that with a for-each loop and you also can't do that with an Iterator in general (because they don't implement a peek).
Instead, you could use a traditional for loop on your cStickCollection like
for (int i = 0, len = cStickCollection.size(); i < len; i++) {
CStick localCStick = cStickCollection.get(i);
System.out.println(localCStick.getEPIC());
if (i + 1 < len) { // <-- check that there is a "next"
System.out.println("next EPIC is "+cStickCollection.get(i+1).getEPIC());
}
}
Everytime you call testCStickChart.iterator() inside of that loop, you create a new iterator object. So each call to next() is carried out on a new iterator object, returning the first object. What you want to do is to declare a new Iterator<CStick> just before the loop and use it inside the loop, like so:
Iterator<CStick> it = testCStickChart.iterator();
// Print the EPIC out of the Array using the iterator
for (CStick localCStick : testCStickChart) {
System.out.println(localCStick.getEPIC());
//The below line doesn't return the next CStick and I'm not sure why
System.out.println("next EPIC is " + it.next().getEPIC());
}
I am trying to iterate (or use a for each loop) on a Linked list class and be able to change the item (when found) to a passed in parameter.
for(Item n : items)
{
if (n.getKey().equals(key))
{
n = new Item(key, value);
}
}
Does this change of data work or is it temporary (only to be lost when the activation record is deleted)?
You can't iterate over a collection and modify it. You will always get a java.util.ConcurrentModificationException. First off all you need to use an iterator, to remove the item. Then you can use a second list to store the data you want to add.
Here you are an example:
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("This");
linkedList.add("is");
linkedList.add("an");
linkedList.add("test");
LinkedList<String> temp = new LinkedList<String>();
for (Iterator<String> iterator = linkedList.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
if(string.equals("an")) {
iterator.remove();
temp.add("a");
}
}
linkedList.addAll(temp);
You can call iterator.remove() to savely remove the current item from list.
You are using fast enumeration, which protects the list that you are iterating through. If you would like to change the data in the list, you would need to use a traditional for loop.
Basically how fast enumeration works is it makes the array read-only in the block of code because you have no access to what integer the iteration is.
You could do this:
for(int i = 0; i < items.length; i++)
{
if (n.getKey().equals(key))
{
items[i] = new Item(key, value);
}
}
I have the following code:
System.out.println(dislist.size());
for (int k = 0; k < 10; k++) {
System.out.println(k + dislist.get(k).first + dislist.get(k).second);
if (!dislist.get(k).first.equals(Nodename)) {
if (dislist.get(k).first.equals(myfirst) ||
dislist.get(k).first.equals(mysecond) ||
dislist.get(k).second.equals(myfirst) ||
dislist.get(k).second.equals(mysecond)) {
dislist.remove(k);
}
}
}
}
The Problem is: the print at the beginning clearly says that dislist.size() is 10.
However, I get an array out of bounds exception, telling me that the size of the list is no more than 6.
And yes, I DID add new objects to the list a few lines before that.
I guess when the loop starts that has not been finished yet.
Is there a way to force Java (within the same method) to start the loop only when there is really 10 objects in the list?
You're removing elements from the List as you iterate though it. That's the reason the size is changing.
dislist.remove(k);
Create a new list, and add each element you want to remove to it. After your loop is finished, use disList.removeAll(listOfElementsToRemove) to remove them all at once.
Iterator<YourClass> iter = dislist.iterator();
while (iter.hasNext()) {
YourClass obj = iter.next();
if (/* your expression */) {
iter.remove();
}
}