List<Left> resultList = lists.iterator().next();
for (Iterator iterator = lists.iterator(); iterator.hasNext();) {
List<Left> list = (List<Left>) iterator.next();
resultList.retainAll(list);
}
/*for (Left left : resultList) {
System.out.println(left.getData());
}*/
for (Left left : mLeft) {
ArrayList<Left> mTempList = left.getArray();
for (Iterator iterator = mTempList.iterator(); iterator.hasNext();) {
Left left2 = (Left) iterator.next();
System.out.println(left2.getData());
}
}
I am trying to find out the common elements , my original list is getting changed.I mean only last element gets changed when I print the lists.
Any suggestions.
resultList gets assigned to the first element in your collection lists right at the top.
On line 4 you execute retainAll against resultList without changing what resultList is assigned to - it's still pointing to the first object in lists.
You might consider creating a new List<Left> object to check for the common elements, right at the start instead of how you've declared resultList:
List<Left> resultList = new List<Left>();
resultList.addAll ((List<Left>) lists.iterator().next());
...
You would then want to use resultList in the final loop when you print out the elements.
Note that you are still assuming that lists has at least one element - if it's empty you'll get an exception.
Related
I'm trying to iterate a list, wherein each iteration I'm doing one of the below:
Continue to next element (by some logic)
Removing the current element
What I need is that after I'm iterating through all the items, it will continue to iterate until the list is empty (the logic ensures all elements will be removed).
Problem is that after the iterator iterates all the list elements, it didn't continue to run on the elements I didn't remove:
List<Integer> lst = new ArrayList();
lst.add(1);
lst.add(2);
lst.add(3);
Iteartor<Integer> iterator = lst.listIterator();
while (iterator.hasNext()){
Integer curInt = iterator.next();
if (!passTest(curInt)){
continue;
}
iterator.remove();
}
IMPORTANT NOTE: passTest(curInt) logic can be different for each iteration. It means that iteration one can cause continue, then the second and third iterations will cause a removal. PROBLEM is I'm expecting for a fourth iteration (on the first item that wasn't removed).
The solution I've found:
List<Integer> lst = new ArrayList();
lst.add(1);
lst.add(2);
lst.add(3);
Iteartor<Integer> iterator = lst.listIterator();
while (!lst.isEmpty()){
Integer curInt;
if (iteration.hasNext()){
curInt = iterator.next();
} else {
curInt = lst.get(0);
}
if (!passTest(curInt)){
continue;
}
iterator.remove();
}
Is that the right way to achieve that?
Your solution doesn't seem correct. You will first iterate over all the elements of the List, possibly removing some of them. Once you finish iterating over the List, iteration.hasNext() will always return false, so you'll keep getting the first element (due to curInt = lst.get(0)). If you remove that first element, you'll get a different element the next time curInt = lst.get(0) is executed, so the List will become empty in the end, but that doesn't seem like the desired behavior (if it was the desired behavior, you could eliminate the Iterator and just keep getting the first element in a loop and possibly removing it).
You should use nested loops, and re-create the Iterator instance inside the outer loop:
while (!lst.isEmpty()) {
Iteartor<Integer> iterator = lst.listIterator();
while (iterator.hasNext()) {
Integer curInt = iterator.next();
if (passTest(curInt)) {
iterator.remove();
}
}
}
Each iteration of the outer loop creates an Iterator and performs the inner loop.
Each iteration of the inner loop iterates over the elements of the List, and possibly removes some of them.
Once you finish an iteration over the List, you must create a new Iterator in order to iterate over the remaining elements again.
This question already has answers here:
Collection throws or doesn't throw ConcurrentModificationException based on the contents of the Collection [duplicate]
(5 answers)
Closed 6 years ago.
I have tried the following two scenarios:
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("1")) {
arrayList.remove(0);
}
}
The first scenario output is :
---->1
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Test.main(Test.java:83)
Probably the ConcurrentModificationException exception is caused because I'm trying to modify the collection while I'm still iterating it.
In the second scenario I changed the if() condition from value.equals("1") to value.equals("2") and the program does not throw any error.
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
The second scenario output is:
---->1
---->2
In both the scenarios, my program does not reach the 3rd element (Value : 3).
Can you please help me to understand the problem ?
Problem is you are removing element from the list which presend at index 0. Instead of removing from the list use iterator.remove() method. For more info read this.
program code -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
Why list not returning the last element?
Answer -
you are removing element from the list and you already perform iterator action against same list. At the end iterator.hasnext() method returns false so you are not getting last element.
If you want to see it for demo purpose run below sample codes -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
ArrayList : [2, 3]
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
---->3
ArrayList : [1, 3]
By running two pieces of code in debug mode, I found the following.
1st scenario:
Elements saved from arraylist:
After the remove command has been executed:
The ConcurrentModificationException gets thrown at the following line
String value = (String) iterator.next();
2nd Scenario:
The ArrayList will be the same as the second link.
After printing 2, the control breaks from
while (iterator.hasNext())
as iterator.hasNext() = null. Hence it's safe.
I suppose that you encounter the problem only in the first case because you are trying to remove the element pointed by the iterator. In fact, the second scenario succeeds because you remove the first arraylist element that, at that moment, is not pointed by the iterator.
(p.s. I agree with all the various and future answers that will describe you how to solve your problem by showing fragments of code, I just provided you an explanation of what happens)
The ConcurrentModificationException occurs because you are removing the same element (at index 0) that the current iteration of the loop is reading (the one with value = ”1”). In the second case you don't see the exception because you are removing the element at index 0, but are reading the element at index 1 (the one with value = "2"). You cannot remove an element concurrently while reading it unless you use one of the collections that supports concurrency (see java.util.concurrent package)
You are removing an element (remove(0)) while iterating the list, which "shifts the end of the list" towards left by one. So, the next time you check for iterator.hasNext(), it will return false and the original 3rd element never gets processed.
When you iterate on a Collection, you should remove the element with the iterator :
iterator.remove()
In the second code, here :
if (value.equals("2")) {
arrayList.remove(0);
}
you remove the first element of the list. The list has so a size of 2 elements.
The iterator implementation takes into consideration the size of the list to know if it has next elements or not :
public class ArrayList<E> extends AbstractList<E>
...
private class Itr implements Iterator<E> {
public boolean hasNext() {
return cursor != size;
}
}
Since two elements were iterated and that the list has now a size of 2 because you remove one element of it, the iterator considers that it has not next element to iterate on.
If you use an iterator to remove the current element, you have not this side-effect.
I want to loop through a LinkedList using For each and access the element after the one I am at right now. If I would use an Array and the usual for(int i = 0; i < ... ; i++), I would be looking for the element i+1. Is there a possibility of reaching the element after the one I am at right now?
Is there a possibility of reaching the element after the one I am at right now?
If you use a simple "for each" loop, then No. The "current position" within the list is encoded to the list's Iterator. When you use "for each", the Iterator is hidden from your application.
Instead you need to do something like this:
List<Element> list = ...
Element current = null;
Element next = null;
Iterator<Element> it = list.iterator();
while (it.hasNext()) {
current = next;
next = it.next();
if (current == null) {
continue;
}
// process 'current' and use `next` when you need to refer to
// the following on element.
}
if (next != null) {
// process 'next' as the last element.
}
Notes:
If null is a valid list element, then use a flag instead.
Using two iterators for the same list might give you a neater solution.
You could also do something similar to this using a for each ... and keeping track of the "previous" element in a variable, like I do above. See #Jezor's answer.
It is inadvisable to use get(i) on a (large) LinkedList because get(int) is an O(N) operation for a LinkedList in the general case.
You can neither determine the index of next element in enhanced for loop nor it's value.
You can keep the reference to previous element though:
// List is initialized somewhere in the code.
List<Element> elements = ...;
Element previousElement = null;
for (Element element: elements) {
if (previousElement != null) {
// ... your code here...
// previousElement is elements[i]
// element is elements[i + 1]
}
previousElement = element;
}
In the above example you can instantiate previousElement with a null object to avoid the null check.
What you really want to use is good, old for loop with a counter:
List<Element> elements = ...;
for (int i = 0; i < elements.size(); ++i) {
// elements.get(i) is elements[i]
// elements.get(i + 1) is elements[i + 1]
// But be careful, (i + 1) will be out of bounds for the last element!
}
Don't make your life unnecessarily complicated.
If you're using the auto-iterator for-each style loop such as:
for (T elem: myList) {
// ...
}
then there isn't an immediate way to access the "next" element while you're looking at the current one without saving a reference to the element you last saw. It is also possible with using indexOf, but this approach gets very messy when duplicates are found in the list. Regardless, I think your problem would be better addressed using indexing over the list instead.
If you're iterating over your LinkedList object using indexed-based access (as opposed to an iterator or for-each, for example,) you can do:
for (int i = 0; i < myList.size(); i++) {
// ...
if ((i + 1) < myList.size()) {
T nextElem = myList.get(i+1); // fetch the element at the next index
// then do whatever you want with "nextElem"
}
// ...
}
where T refers to the type of LinkedList you are using, i.e. String if your list definition was something like LinkedList<String> myList = new LinkedList<>();.
I want to iterate through some kind of list, checking if its elements meet a property, and if they don't deleting them from the array. What I've thought is something like this:
int index = 0;
for(int i = 0; i < list.size(); ++i) {
if(list.isProperty()) list.delete(index) //We delete the element at list[index]
else ++index;
}
Maybe those aren't the real methods of the list interface in java, but they're quite self-explanatory.
Is this a good approach? Which data structure would fit best if I have to run this operation many times? I don't think an arrayList would work as I'd have to be moving around elements each time I delete and I can't ensure the elements I'll remove are in the head or the tail of the list either.
You can achieve it using iterator.Without having concurrent modification exception.
Say your list consists of object A
List<A> list = new ArrayList<A>();
Iterator<A> iterator = list.iterator();
while (iterator.hasNext()) {
A current = iterator.next();
if(current.isProperty()) {
iterator.remove();;
}
}
You should remove an element from a List using an Iterator. You can use this with ArrayList.
List<YourDataType> yourList = new ArrayList<YourDataType>();
Iterator<YourDataType> it = yourList.iterator();
while (it.hasNext())
it.remove();
With this you can use if-else to specify the element, which should be removed.
This should give you some hints, why you should use an Iterator.
2nd question, which is continue of first.
I have got two Lists of strings. There is an List of strings (asu) - M1, M2, M3 ... As well as an List of string (rzs) - M1, M2, M3 and all possible combinations thereof. The need for each element (asu) (for example M1) to find an element in (rzs) (M1, M1M2, ..), which contains (e.g. M1). Example: took M1 from (asu) and will start search for duplicate(contain) in (rzs). We found M1M2 in (rzs), it contains M1. After that we should delete both elements from lists. Great thanks to No Idea For Name helped for modification this code. But the program always fails because AbstractList.remove error. Please help to implementation logic and tuning code!
Imports..........
public class work{
List<string> asu = Arrays.asList("M1","M1","M1","M3","M4","M5","M1","M1","M1","M4","M5","M5");
List<string> rzs = Arrays.asList("M1","M2","M3","M4","M5",
"M1M2","M1M3","M1M4","M1M5","M2M3","M2M4","M2M5","M3M4","M3M5","M4M5"
,"M1M2M3","M1M2M4","M1M2M5","M1M3M4","M1M3M4","M1M4M5","M2M4","M2M5");
public static void main(String[] args) {
work bebebe = new work();
bebebe.mywork();
}
List<string> tmp1 = new ArrayList<string>();
List<string> tmp2 = new ArrayList<string>();
System.out.println(Arrays.deepToString(rzs));
System.out.println(Arrays.deepToString(asu));
for (string curr : asu){
for (string currRzs : rzs){
System.out.println("New iteration ");
if (currRzs.contains(curr)) {
System.out.println("Element ("+curr+") in ASU =
element ("+currRzs+") in RZS");
if(tmp1.contains(curr) == false)
tmp1.add(curr);
if(tmp2.contains(currRzs) == false)
tmp2.add(currRzs);
}
}
}
for (string curr : tmp1){
asu.remove(curr);
}
for (string currRzs : tmp2){
rzs.remove(currRzs);
}
You should try to make use of removeAll() or retainAll() methods of Collection.
For example:
List<String> aList = new ArrayList<String>();
aList.add("a");
aList.add("b");
aList.add("c");
aList.add("d");
aList.add("e");
List<String> bList = new ArrayList<String>();
bList.add("b");
bList.add("e");
bList.add("d");
aList.removeAll(bList);
will give you the "a" and "c" elements left in aList
While if you try to make use of retainAll() method:
aList.retainAll(bList);
will give you "b", "d" and "e" elements left in aList;
retainAll() is used to remove all the elements of the invoking collection which are not part of the given collection.
removeAll() is used to remove all the elements of a collection from another collection.
So, it all depends on your use-case.
EDIT
If in any case you want to remove some elements from these collections while iterating conditionally then you should first obtain the Iterator<Type> then call the remove() method over it.
Like:
while(iterator.hasNext()){
String str = iterator.next();
if(str.equals('test')){
iterator.remove();
}
}
Don't remove items from list using foreach loop. Use classic for and iterate over elements, and when removing item, decrease iterator.
To safely remove elements while iterating use Iterator.remove method:
The behavior of an iterator is unspecified if the underlying
collection is modified while the iteration is in progress in any way
other than by calling this method.
Iterator<String> i = tmp1.iterator();
while (i.hasNext()) {
i.next(); // must be called before remove
i.remove();
}
Also it is easier to remove all collection from another by simply calling:
asu.removeAll(tmp1);
instead of List you can use Set, which will remove automatically the duplicate elements...
You can use removeAll() method to remove collection of elements from the list instead of removing one by one.
use
asu.removeAll(tmp1);
instead of
for (string curr : tmp1)
{
asu.remove(curr);
}
and use
rzs.removeAll(tmp2);
instead of
for (string currRzs : tmp2)
{
rzs.remove(currRzs);
}
update
I trace out your problem.The problem lies in Arrays.asList() method.
According to Arrays#asList
asList() returns "a fixed-size list backed by the specified array". If you want to resize the array, you have to create a new one and copy the old data. Then the list won't be backed by the same array instance.
So create a duplicate ArrayList for the lists.Like this
List<string> asuDuplicat = new ArrayList<string>(asu);
List<string> rzsDuplicat = new ArrayList<string>(rzs);
use asuDuplicat,rzsDuplicat.
asuDuplicat.removeAll(tmp1);
rzsDuplicat.removeAll(tmp2);