Iterating over List of Lists - java

I'm trying to iterate over a list os lists but I'm getting CME all the time even using Iterator to remove and add elements while iterating over the lists.
I searched here in the community for similar questions but those I found didn't help me. Really hope you guys help me to figure out how to do what I need to do.
I have I ListIterator<List<Event<T>>> itrListsEvent = partitionSubLists.listIterator();
partitionSubLists is A list of lists. So I have one bigger List and inside it I have four sublists.
I need to iterate over the sublists, and while iterating I remove and add elements. After finishing to iterate over the first sublist, I need to go forward to iterate over the second sublist and so on and so forth.
This is what I've done so far:
public List<List<Event<T>>> partitionedLists (List<Event<T>> list)
{
int listSize = list.size();
int partitionSize = listSize / 4;
List<List<Event<T>>> partitions = new ArrayList<>();
for (int i = 0; i < listSize; i += partitionSize)
{
partitions.add(list.subList(i, Math.min(i + partitionSize, list.size())));
}
return partitions;
}
List<List<Event<T>>> partitionSubLists = partitionedLists(List<Event<T>>);
ListIterator<List<Event<T>>> itrListsEvent = partitionSubLists.listIterator();
while(itrListsEvent.hasNext())
{
List<PrefixEvent<T>> listPE = new ArrayList<Event<T>>();
listPE = itrListsPrefixEvent.next();
ListIterator<Event<T>> itrEvent = listPE.listIterator();
while(itrEvent.hasNext())
{
//here I remove and add elements inside the sublist.
//when finished, I need to go back to first while and go forward to the next sublists
//and in this moment, i got ConcurrentModificationException
itrEvent.remove()
.
.
.
// some code here
itrEvent.add(new Event<T>);
}
}

It's rather unclear exactly what you're trying to achieve. As far as I understand, you could achieve it like this:
List<PrefixEvent<T>> listPE = itrListsPrefixEvent.next();
// No iterator.
for (int i = 0; i < listPE.size(); ++i) {
listPE.remove(i);
// some code here
listPE.add(i, new Event<>());
}
This avoids a ConcurrentModificationException because you don't structurally modify the list after creating an Iterator.
If you don't actually require the "one element removed" list in between the itrEvent.remove() and itrEvent.add(new Event<T>()), you can continue to use the ListIterator, and then set the value to a new value:
itrEvent.set(new Event<>());

Related

Removing duplicates from an ArrayList?

Good afternoon everyone, I am currently studying for my Java Final and I have a review exercise that asks the reader to create a program that asks the user to input 10 integers and then to use a method to remove duplicates and display the distinct list. The method is provided for you as well.
I've gotten the majority of the code written, in fact I thought I was done until I realized that the for loop is removing more than just duplicates..
Here is my code:
public class lab25 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int i;
//Create array list
ArrayList<Integer> numbers = new ArrayList<>();
System.out.println("Please enter 10 numbers!");
//Populate
for(i=0; i<10; i++) {
numbers.add(input.nextInt());
}
System.out.println("Your numbers are: " + numbers.toString());
removeDuplicate(numbers);
System.out.println("The distinct numbers are: " +numbers.toString());
input.close();
}
public static void removeDuplicate(ArrayList<Integer> list) {
int i;
for(i=0; i<list.size(); i++) {
if(list.contains(list.get(i))) {
list.remove(i);
}
}
}
}
Just curious what I have done wrong here? I think my issue might lie in my for loop.. Thanks to all who answer.
list.contains(list.get(i)) always returns true, since the i'th element of the List is contained in the List.
Therefore removeDuplicate is trying to remove all the elements (but you only remove half of them, since after removing the i'th element you skip the new i'th element).
There are many ways to remove duplicates. The most efficient involve using a HashSet. If you want to find duplicates using only List methods, you can check if list.lastIndexOf(list.get(i)) > i.
The expression list.contains(list.get(i)) is always true, since you're asking if the list contains some element from the list. You need to check if list.get(i) is contained in the first i-1 items in the list, which I recommend doing with a loop.
Be aware that a loop with list.remove will run slowly, since removing item i from an ArrayList is done by replacing item i with i+1, then replacing item i+1 with i+2 and so on. This means it takes around length^2 time to make a loop that calls remove in every iteration. The function list.contains has the same problem, as it has to go through the entire list. This may not matter if you have 10 items, but if you had a list with a million items, it would take a long time to run.
The easiest ways is to use Stream.distinct():
public static List<Integer> removeDuplicate(List<Integer> list) {
return list.stream().distinct().collect(Collectors.toList());
}
In case you are free to choose collection, you should use LinkedHashSet instead. It holds ordered unique numbers.
A solution could be this one. I startet at the end of the list that I don't delete indexes the loop has to visit in the future.
public static void removeDuplicate(ArrayList<Integer> list) {
int i = list.size() - 1;
while (i > -1) {
// check for duplicate
for (int j = 0; j < i; j++) {
if (list.get(i) == list.get(j)) {
// is duplicate: remove
list.remove(i);
break;
}
}
i--;
}
}
You are taking the list.get(i) which of course is present in the list, and you will delete all of the values in the end.
You could remove them by using a set:
Set<String> hs = new HashSet<>();
hs.addAll(numbers);
numbers.clear();
numbers.addAll(hs);
If you want to keep the current order and do not want to use set.
List<String> notduplicatedList =
new ArrayList<>(new LinkedHashSet<>(String));

Modifying an Array list while I am iterating over it

How can I modify an arraylist while iterating over it? I would like answers that only deal with whilst I am iterating it please no answers regarding that I can save it and then modify it.
for (ListIterator<CardGroup> ShortSeqGroupListIterator = ShortSeqGroupList
.listIterator(); ShortSeqGroupListIterator.hasNext();) {
CardGroup ShortSeqGroup = ShortSeqGroupListIterator.next();
System.out.println("Iteration --- "+ShortSeqGroup.getCardList());
for (ListIterator<CardGroup> cardGroupListIterator = this.cardGroupList
.listIterator(); cardGroupListIterator.hasNext();) {
CardGroup cardGroup = cardGroupListIterator.next();
if (cardGroup.getCardGroupType() == CardGroupType.PURESEQUENCE
|| cardGroup.getCardGroupType() == CardGroupType.SHORTSEQUENCE) {
continue;
}
Listindex = cardGroupListIterator.nextIndex() - 1;
listOfIndex.add(Listindex);
cardGroup.setCardGroupType(CardGroupType.NONE);
this.mergeExtraGroups();
}
ShortSeqGroup.setCardGroupType(CardGroupType.NONE);
this.mergeExtraGroups();
this.markSets();
this.markSequences(false);
int PenaltyPointsShSeq = totalPenaltyOfUser(this.cardGroupList);
PenaltyMapShortSeq.put(PenaltyPointsShSeq, this.cardGroupList);
this.cardGroupList = clonedCardGroupList;
System.out.println("&************************&");
this.print();
}
NavigableMap<Integer, List<CardGroup>> descendedPenaltyMapShortSeq=PenaltyMapShortSeq.descendingMap();
System.out.println(descendedPenaltyMapShortSeq.firstKey());
I want to operate on the list and then after saving the operation I need to get the previous state of the list back ..
The problem is of course Concurrent modification exception.
The this.cardList is the one I am operating on and the cloned cardgrouplist is a copy of it...
The cardGrouplist 1st element again contains:
An arraylist
Don't use an Iterator, switch it out for a normal for(int i = 0; i < list.length; i++) loop.
It look messy to modify a collection while iterating. I would suggest you to iterate to collect the list of items to add/delete first. Then, perform add/delete the collected item accordingly.

How to find sublist (intersection) among items in one Arraylist of integer in java?

I have a Hashtable<List<Integer>, List<Triples>> ResultIPM2 = new HashTable<>(), I want to work on the key part which is aList<Integer>contains three patterns {[2,3,4] , [3,2,4,3] , [2,4,3]}.What I want to do is, I want to remove [2,4,3] because it is a subset of [3,2,4,3]. How can I report just [2,4,3] and [3,2,4,3] .
Note that the intersection must be in the same order as the smaller list.
For example, if instead of [3,2,4,3] we had a pattern [3,2,3,4] we wouldn't remove any pattern. by "remove" I mean not showing the pattern when reporting it.Here is a piece of my code:
Please don't care about the other answers because I had to edit this old question in order to be able to ask a new question.Thank you
Set<List<Integer>> key = resultsIPM2.keySet();
boolean maximal = false;
for(List<Integer> p1 : key){
for(List<Integer> p2:key){
if(!p2.equals(p1)){
if(p1.containsAll(p2)){
System.out.println(p1);
}
}
}
}
You can't use the enhanced for loop to remove from the list. Use an explicit Iterator.
List<List<Pair>> newPattern = new CopyOnWriteArrayList<>();
//Algorithm : end of Line 14
Iterator<List<Pair> iter = ptList.iterator();
while(iter.hasNext()){
List<Pair> list = iter.next();
Iterator<Pair> pairIter = list.iterator();
while(pairIter.hasNext()){
Pair pair = pairIter.next();
if (getFrequency(pair) < minSupp){
pairIter.remove();
newPattern.add(list);
}
}
}
Iterator.remove() is the only safe way to modify a collection during iteration.
Use Iterator instead of the for-each construct when you need to remove the current element.
The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
Now regarding the code which you said dint work is because
Iterator <Pair> iter = pairList.iterator();
should be something like this
Iterator<List<Pair> iter = ptList.iterator();
then again when you do iter.next();
It will give you List<Pair> list not this Pair pair. So you need to iterate over the list again the compare and remove.
Eran gave you a very nice example follow that
You can not modify a List while you are in a foreach loop of this list. You can use a normal for-loop which just increments an int to get your element:
List<List<Pair>> newPattern = new CopyOnWriteArrayList<>();
//Algorithm : end of Line 14
for(int i = 0; i < ptList.size(); i++){
List<Pair> list = ptList.get(i);
for(int j = 0; j < list.size(); j++){
Pair pair = list.get(j);
if (getFrequency(pair) < minSupp){
list.remove(j);
j--;
newPattern.add(list);
}
}
}

get value that occurs more than one in a list?

What are the the best methods to get values that occur more than once in a large list of words without slowing my run time?. My file contains 1xx,xxx words and I put them into a linked list. Now, I want to get only the words that occur more than once out of that list.
For example, if a list contains:
....This is is is just a test test....
I want to get is and test and put them into another list using an iterator.
I don't know if my code is right, and I think that this is not the best solution to approach for this problem.
for(int i = 0; i < word.size(); i++) {
Word s = word.get(i);
Word s1 = word.get(i+1);
if(s.equals(s1)) {
newWord.add(s);
}
}
Put them all into HashSet instead of list and check the return value of add() method.
HashSet<Word> wordSet = new HashSet<>();
for(int i = 0; i < word.size(); i++) {
if(!wordSet.add(word.get(i)){
//Found duplicate
}
}
Note that you can also do it during/instead of creation of the list of the words.
Build a hashmap with the word as key and it count as value.
for(each word in list)
{
count = 1;
if(map.contains(word))
{
count = map.get(word);
}
else
count = 1;
map.put(word,count);
}
Then iterate over the hashmap and check if values is 1, and add the word to your list.
If you can sort the list, then finding duplicates is quick and easy.

Getting most recent objects in a list

How can i get the most recent objects in a List?
I have tried
int i = 5;
while(i > 0) {
Object o = list.get(list.size() - i);
i--;
}
but to no avail, i could be doing it wrong, but if i am i am unware how to fix my mistake :/
(The problem is it is still giving me the entire list)
You could just reverse the list then iterate over it:
// Your original list
List<Object> list = new ArrayList<Object>(); // Populated elsewhere
// Make a copy, so you don't corrupt the original list
List<Object> reverseList = new ArrayList<Object>(list);
// Reverse the order of its elements
Collections.reverse(reverseList);
// Now iteration will be in "latest added first" order - ie LIFO
for (Object o : reverseList) {
// Do something with o
}
I think that you're expecting your code to change the original list, but this is a wrong assumption since the code simply gets an object held by the list and doesn't remove it. Then you discard the object held by o, so there is no way to test if your method is working or not. To solve this, you've got to save the stuff produced from your method to test if it works or not.
int i = 5;
List savedJunk = new ArrayList();
while(i > 0) {
Object o = list.get(list.size() - i);
savedJunk.add(o);
i--;
}
for (Object foo : savedJunk) {
System.out.println(foo);
}
It's a good question and you pretty much had the right answer. The central idea is that items in a list appear in the order in which you added them, so to get the most recent item you need to go through the list in reverse. Here is one way to do that with a for loop.
ArrayList<String> myList = new ArrayList<String>();
myList.add("one");
myList.add("two");
myList.add("three");
myList.add("four");
for (int index = myList.size() - 1; index >= 0 ; index--) {
System.out.println(myList.get(index));
}
The output of the above code is:
four
three
two
one

Categories