简体   繁体   中英

How do I copy Iterator Object?

This is an sample code, looking for generalized solution.

   List<String> names = new ArrayList<String>();
    for(int i=0; i<names.size()-1; i++){
        for(int j=i+1; j<names.size(); j++){
            if(names.get(i) == names.get(j)) {
                //return true;
            }
        }
    }

I want replace above for-loop by enhanced for-loop. so tried tried like this. Replaced above for-loop by iterator :

    String name;
    Iterator<String> itr2;
    Iterator<String> itr1 = names.iterator();
    while(itr1.hasNext()) {
    // for(name=itr1.next(); itr1.hasNext(); ) {
        name = itr1.next();  // iterating itr1
        itr2 = itr1;
        while(itr2.hasNext()){
            if(name.equalsIgnoreCase(itr2.next())) {  // iterating itr2
                return true;
            }
        }
    }

we are iterating the itr2 but itr1 also changing. this because of assining the itr1 = itr2. is it possible to copy iterator object instead of assigning?. Instead iterator any other logic also welcome.

Thanks.

If you want to use enhanced for you can't access the iterators directly and you can't/shouldn't reassign iterators in any case.

Instead, try with sublists and an additional index counter:

List<String> names = Arrays.asList( "a", "b", "a", "b", "c" );

int i = 0;
for( String n : names.subList( 0, names.size() - 1) ) {
  for( String s : names.subList( i + 1, names.size() ) ) {
    if( n.equals( s )) {
      return true;
    }
  }

  i++;
}

That's not that much better than your original version and is only meant for education purposes. There might be better ways to achieve your actual goals.

Alternatively, using Java 8 you could make use of streams:

boolean hasDuplicates = IntStream.range( 0, names.size() - 1 )
  .filter( i -> names.subList( i + 1, names.size() ).contains( names.get( i ) ) )
  .findAny()
  .isPresent();

On some level, to copy an iterator, you are going to need to make a new iterable. So the easiest thing to do is just

List<String> itor2 = new LinkedList();
for(String s : itor)
    itor2.add(s);

Of course, if you have to make a new object anyways, and your just checking for duplicates, I would instead just iterate over the list once, adding to a dictionary like HashMap if I haven't seen this value yet.

Seems like you are trying to find out if you have duplicates in the list (ignoring casing). You don't necessarily have to use for loops. If you're looking for a simple true or false value. You can:

public boolean hasDuplicatesIgnoreCase(List<String> names)
{
    return names.stream()
            .map(String::toLowerCase)
            .distinct()
            .collect(Collectors.toList())
            .size() != names.size();
}

This is not an answer to the question you asked, but may be a solution to your problem. Otherwise @Thomas has the best answer using sub-lists.

Seems like you want to check if a list already has a name and return true if present? I'm not sure if it's a proper use but I managed to do it in this way to achieve the effect you requested.

    List<String> names = Arrays.asList( "a", "b", "c", "d", "a" );
    final Set<String> set = new HashSet<>();

    for (String name: names) {
        if (!set.add(name)) return true;
    }

    return false;

set.add returns false when an element has been added already, therefore trying to do so will tell us if the name is already there or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM