Iterating a Collection more than once - java

I am having trouble using Iterator in java.
it=myHash.iterator();
while (it.hasNext())
if (it.next() satisfying something)
do something
while (it.hasNext())
if (it.next() satisfying something)
it.remove();
I am trying to iterate hashset twice, and the first loop making it.hasNext() return false. How to i resolve this?
I tried even adding the edit as you guys suggested, still not working...

You're reusing the same iterator - and that's been invalidated by adding new items to the set.
You should call iterator() again on the set:
it = set.iterator();
You can't reset the existing iterator
EDIT: Here's some sample code which shows this working:
import java.util.*;
public class Test {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("food");
set.add("bad");
set.add("hungry");
set.add("neighbour");
Iterator<String> it = set.iterator();
// Remove any string longer than 4
while (it.hasNext())
{
if (it.next().length() > 4)
{
it.remove();
}
}
set.add("new long text");
set.add("x");
// Remove any string shorter than 4
it = set.iterator();
while (it.hasNext())
{
if (it.next().length() < 4)
{
it.remove();
}
}
// Dump the results
for (String x : set)
{
System.out.println(x);
}
}
}
This gives the results "new long text" and "food".

Ideally, what you are looking for is a reset operation on an Iterator. Iterators are meant to be unidirectional and one-time use, as such they don't have support for reset in Java.
You can either get hold of a new Iterator instance or use ListIterator interface which allows you to look backwards using previous().
Edit:
You are using remove() on the iterator which is also removing elements from the original set. In such a case you should consider making a copy of the set since you want to iterate over the elements all over again:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorSnippet {
public static void main(String[] args) {
final HashSet<Integer> myHash = new HashSet<Integer>();
myHash.addAll(Arrays.asList(1, 2, 3, 4, 5));
// make copy before using iterator with remove
final HashSet<Integer> myHash2 = new HashSet<Integer>(myHash);
Iterator<Integer> it = myHash.iterator();
System.out.println("First go...");
while (it.hasNext()) {
System.out.println(it.next());
it.remove();
}
it = myHash2.iterator();
System.out.println("Second go...");
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

Related

Java PowerSet -prints only one

Having a problem, only printing one instead of each powerset and I can't quite spot it.
Trying to write a program that gives out a powerset of a given set.
import java.util.HashSet;
import java.util.Iterator;
public class PowerSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
HashSet<HashSet<String>> powerset;
set.add("a");
set.add("b");
set.add("c");
set.add("d");
powerset = powerset(set);
System.out.println(powerset);
}
public static HashSet<HashSet<String>> powerset( HashSet<String> set){
if (set.size()== 0) {
HashSet<HashSet<String>> pset = new HashSet<HashSet<String>>();
HashSet<String> emptySet = new HashSet<String>();
pset.add(emptySet);
return pset;
} else {
HashSet<String> tmp;
Iterator<String> it = set.iterator();
String elt = it.next();
set.remove(elt);
HashSet<HashSet<String>> oldpset = powerset(set);
HashSet<HashSet<String>> newpset = new HashSet<HashSet<String>>();
Iterator<HashSet<String>> psetit = oldpset.iterator();
while(psetit.hasNext()){
tmp = psetit.next();
newpset.add(tmp);
tmp.add(elt);
newpset.add(tmp);
}
return newpset;
}
}
}
One issue I see is that you remove the element elt from set before calling powerset(set). Because Java objects act as pointers, when you remove an element from set at for the current call to powerset, you are modifying all references to it (even references stored on the stack from previous calls).
Another issue I see is that you use set.remove(elt), you should be using it.remove() or you will mess up the iterator.

Deleting elements from list using another list

I am trying to delete the elements from list1 that are in list1
package listCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Arry2List {
public static void main(String[] args) {
String[] s = {"INDIA" ,"JAPAN","THAILAND","MALAYSIA"};
ArrayList<String> list1= new ArrayList<String>();
String[] s1 = {"THAILAND","MALAYSIA"};
ArrayList<String> list2= new ArrayList<String>();
for(String temp : s)
{
list1.add(temp);
}
for(String temp : s1)
{
list2.add(temp);
}
//removing elements from list1 that are in list2
System.out.println("In list1 **************");
for (String t : list1)
{
System.out.println(t);
}
System.out.println("In list2 **************");
for (String t1 : list2)
{
System.out.println(t1);
}
//editlist(list1,list2);
Iterator<String> i=list1.iterator();
while( i.hasNext() )
{
if ( list2.contains( i.hasNext() ) )
{
i.remove();
}
}
System.out.println("In list1 again **************");
for(int i1 =0;i1<list1.size();i1++)
{
System.out.println(list1.get(i1));
}
}
}
Output should be INDIA,JAPAN.
List1 should contain only those elements which are not in the list2.
I am a beginner to Core Java and trying to learn collections.
In the loop that checks the element using List.contains(), you're passing a boolean (i.hasNext() returns whether the iterator has more elements) instead of the element. This causes the loop to run infinitely because you never call Iterator.next() to get the next element. You should use:
if (list2.contains(i.next())) {
instead of
if (list2.contains(i.hasNext())) {
It's better practice to also save the next element in a variable for re-usability:
while (i.hasNext()) {
String element = i.next();
if (list2.contains(element)) {
i.remove();
}
}
There is a built-in method to do that:
list1.removeAll(list2)
[EDIT]
You can create the lists easier using Arrays.asList:
List<String> list1 = new ArrayList<String>(Arrays.asList("INDIA", "JAPAN", "THAILAND", "MALAYSIA"));
List<String> list2 = Arrays.asList("THAILAND", "MALAYSIA");
list1.removeAll(list2);
[EDIT2]
The Arrays.asList produces unmodifiable list, so we have to use it to initialize a modifiable one.
[EDIT3]
Your code doesn't work because you don't advance the iterator. i.hasNext() only checks if there is a next element. It returns true or false, not the element itself. Here is how to fix this:
while (i.hasNext()) {
if (list2.contains(i.next())) {
i.remove();
}
}
You can also iterate over the list2 elements and remove them from list1:
for (String el : list2) {
list1.remove(el);
}

Printing the values in an intList

I have an array 'store' that stores a number of LinkedLists called intList.
How do I print the values held in each list? I tried to print it as follows:
system.out.println(store[i].toString);
but get the following in return:
intList#16ad9f5d
or something similar.
Any help would be great, thanks
A java.util.LinkedList has a nice toString() method (so no need to write it yourself, reinvent the wheel etc.), so most probably you don't call it at all. Seems like you're doing something like toArray().toString(), or maybe store.toString().
Extend LinkedList and implement toString().
Public class YourLinkedList<String> extends LinkedList<String> {
//You code goes here or blank
#Override
public String toString() {
return Arrays.toString(this.toArray());
}
}
You will get output as : [fdf, fdfdf, fdfdf]
for(List l : arr)
{
Iterator it = l.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
Something like this might work...
I think This code helps to you.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Test {
public static void main(String args[])
{
LinkedList<Integer> l1=new LinkedList<Integer>();
l1.add(1);
l1.add(2);
LinkedList<Integer> l2=new LinkedList<Integer>();
l2.add(3);
l2.add(4);
LinkedList<LinkedList<Integer>> sort=new LinkedList<LinkedList<Integer>>();
sort.add(l1);
sort.add(l2);
for(List l : sort)
{
Iterator it = l.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
}
Use iterator as this :
Iterator iter = yourList.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}

To get the Iterator running in Java

I have the following code sample, im pretty sure the first block should be placed in the main(), but where do I place the second block to make this Iterator example work?
List<String> myList= new ArrayList<String> ( );
Where do i place this? Would I need to create a second class?
static void printAll(ArrayList myList)
{
Iterator it = myList.iterator();
}
then there's this typical iterator pattern....is this in any way related to the second code block?
static void printAll(ArrayList myList)
{
Iterator it = myList.iterator();
Object temp;
while( it.hasNext() )
{
temp = it.next();
System.out.println( temp );
}
return;
}
It isn't clear what you want to achieve, if you are asking how to pass your ArrayList (local variable in main) to the printAll method, do something like below:
public class XYZ {
static void printAll(ArrayList myList)
{
Iterator it = myList.iterator();
Object temp;
while(it.hasNext() )
{
temp = it.next();
System.out.println( temp );
}
return;
}
public static void main(String...args){
List<String> myList= new ArrayList<String> ( );
myList.add("Hello");
myList.add("World");
printAll(myList);//passing myList to printAll
}
}
Is there a reason you're trying to use an interator?
You can do something like this, assuming you're on Java 5.
List<String> myList= new ArrayList<String> ( );
// set up list... etc.
for(String currentString : myList) {
System.out.println(currentString);
}
Iterators are only useful if you need to remove some element of the collection while traversing it (using the Iterator.remove() method). Otherwise, just use a for-each loop.

How to remove strings of length 5 from a set?

I want to remove strings of length 5 from a set, but it keeps outputting the set itself.
public void remove5()
{
Set<String> newSet = new HashSet<String>();
newSet.add("hello");
newSet.add("my");
newSet.add("name");
newSet.add("is");
newSet.add("nonsense");
for(String word: newSet)
{
if(word.length()==5)
{
newSet.remove(word); // Doesn't Help - throws an error Exception in thread "main" java.util.ConcurrentModificationException
}
}
System.out.println(newSet);
}
I want the output to be:
my
name
is
nonsense
(hello was removed because it's 5 characters)
But I get this everytime:
hello
my
name
is
nonsense
Can you please help?
Iterator<String> it= newStr.iterator();
while(it.hasNext()) { // iterate
String word = it.next();
if(word.length() == 5) { // predicate
it.remove(); // remove from set through iterator - action
}
}
For actually modifying your set, you need to do something like this:
Iterator<String> iter = newSet.iterator();
while (iter.hasNext())
if (iter.next().length() == 5)
iter.remove();
Since Strings are immutable, you can't modify the ones that were already added to the set, and anyway, even if you could modify them in-place, replacing them by "" would not remove them from the set.
As other suggested you cannot change a String reason being, Code snippet:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class TestString {
public void remove5() {
Set<String> newSet = new HashSet<String>();
newSet.add("hello");
newSet.add("my");
newSet.add("name");
newSet.add("is");
newSet.add("nonsense");
for (Iterator<String> iter = newSet.iterator(); iter.hasNext();) {
if (iter.next().length() == 5) {
iter.remove();
}
}
System.out.println(newSet);
}
public static void main(String[] args) {
new TestString().remove5();
}
}
If you iterate over the set and in the loop you remove the object, it will throw you ConcurrentModificationExceptionas HastSet iterator is a fail fast Iterator.
When you find a string of length 5, you need to remove it from the set:
newSet.remove(word);
As it is, you appear to be trying to change word to an empty string, but strings are immutable. What your call actually does is return an empty string.
Strings are immutable, changes made to the String word or any other String will not reflect in the string of Set
add
if(word.length()==5)
{
word.replaceAll(word, "");
newSet.remove(word);
}
you can refer to this function of HashSet
remove(Object o)
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/HashSet.html
Strings are immutable in Java, that means when you call word.replaceAll(word,""), it returns the String "" (which you aren't assigning to anything). The word doesn't change and the Set is still pointing to the old value of word. You need to remove word from the Set itself.
int i = 0;
Set<String> newSet = new HashSet<String>();
newSet.add("hello");
newSet.add("my");
newSet.add("name");
newSet.add("is");
newSet.add("nonsense");
for(String word: newSet)
{
if(word.length()==5)
{
newSet.remove(i);
}
i++;
}

Categories

Resources