Is there a simple method to check if an element is contained in an iterable or iterator, analogous to the Collection.contains(Object o) method?
I.e. instead of having to write:
Iterable<String> data = getData();
for (final String name : data) {
if (name.equals(myName)) {
return true;
}
}
I would like to write:
Iterable<String> data = getData();
if (Collections.contains(data, myName)) {
return true;
}
I'm really surprised there is no such thing.
In Java 8, you can turn the Iterable into a Stream and use anyMatch on it:
String myName = ... ;
Iterable<String> data = getData();
return StreamSupport.stream(data.spliterator(), false)
.anyMatch(name -> myName.equals(name));
or using a method reference,
return StreamSupport.stream(data.spliterator(), false)
.anyMatch(myName::equals);
Guava has the functions Iterables.contains and Iterators.contains which do what you want. You can look at the source to see how to implement them yourself.
An iterator is a sort of cursor which can be moved over the elements of any collection of elements. So its inner state is mainly the pointer to the current element. If you would try to find out whether it "contains" a certain element you would have to move the cursor and therefore modify the inner state. Modifying the state by simply asking a question is surely a bad thing to do.
That is even the problem with the mentioned Guava. It will modify the iterator object by simply calling the contains method.
An iterable on the other hand is simply an interface telling the compiler that there is something to iterate over. In most cases the iterable object will be the collection itself. If you would add methods like "contains" to the interface Iterable you would get a (simplified) version of the Collection interface - which already exists. So there is no need for that.
If you are stuck in your code at some place where you have a reference to an iterable but need functionality of a collection you should think about refactoring your code. Either you should use the interface collection consistently or ask yourself why you should better not call collection methods at this point. So your problem is most probably a result of a suboptimal code design.
On the other hand I would consider it to be a strange thing to use Iterable as type for parameters or variables anyway. Technically you can do this but I think it is meant to be used in loops only.
From the JavaDoc for Iterable:
Implementing this interface allows an object to be the target of the "foreach" statement
I'm sorry to say what you're trying to do is impossible.
.contains is a method of the interface Collection and not Iterable so maybe you can use that interface.
An Iterator is like a pointer/reference to an element in a collection. It is not the collection itself. So, you can't use iterator.contains(). Also, an Iterable interface is used to iterate over a collection using a for-each loop. A collection and Iterator / Iterable are different.
Related
I'm currently learning Kotlin coming from Java. In Java, doing
for(String s:stringList){
if(condition == true) stringList.remove(s);
}
doesn't work, as you can only read data with for each. Does this also apply to Kotlin?
It's the same restriction as in Java - when you're iterating over a collection, you're limited to modifying it through the Iterator's remove() method
Removes from the underlying collection the last element returned by this iterator (optional operation). This method can be called only once per call to next(). 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.
Kotlin has its own equivalent (bearing in mind Kotlin uses the concept of mutable and immutable lists, so you can only do this with a MutableList)
The problem with the foreach / enhanced for structure is it doesn't expose the Iterator you need to call remove() on, and you're not allowed to call remove() on the collection itself. And Kotlin's the same - so your options are basically
use for/forEach (but you can't modify the collection)
call the collection's iterator() method and iterate over it yourself (now you can call remove() on it, with the restrictions I quoted)
avoid mutability and produce a new collection
The last one is what you're encouraged to do in Kotlin - instead of modifying a collection, try to use immutable ones and transform them into new collections instead:
stringList.filterNot { condition }
If you get familiar with all the collection functions (yeah, there are a lot of them) you'll get an idea of the ways you can transform A to B, and the convenience functions that are there to help you do it (e.g. filterTo which lets you provide a MutableList to populate with the items you want to keep).
If you do want to modify mutable collections in place though, it's possible but you have to manage it yourself, because it's inherently dangerous and the system can't guarantee you're doing it safely.
Yes, if you rewrite this code in Kotlin, you'll get the same concurrent modification problem:
for (s in stringList) {
if(condition == true) stringList.remove(s)
}
To avoid this problem, you can obtain a mutable iterator from a mutable list and use it to remove elements on the go. But unlike Java, you don't have to iterate it manually with hasNext()/next() calls — you can use the same for operator for iterating it:
val iterator = stringList.iterator()
for (s in iterator) {
if (condition == true) iterator.remove()
}
List<String> stringList;
//fill with strings somehow
Collection<String> stringCollection = (Collection<String>) stringList;
for(String str : stringCollection){
//will this loop be guaranteed to iterate in the order found in stringList
}
I think it is guaranteed that this for-each loop will iterate in the correct order, since the syntactic sugar actually uses an iterator and the iterator() method is overridden in List to have an order. Since the run time type of stringCollection is a List, then it will use the overridden method which starts at the beginning of the list. Is this correct?
Yes, the enhanced for loop will use the iterator of the provided collection. So if b is really a list (runtime type), then the order will be guaranteed.
Note that with the new stream API (Java SE 8) this is a little bit different.
While b.stream() would still guarantee the order, b.parallelStream() wouldn't.
Also see: https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html#ordering
http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#iterator()
Returns an iterator over the elements in this collection. There are no
guarantees concerning the order in which the elements are returned
(unless this collection is an instance of some class that provides a
guarantee).
Yes.
Collection.iterator is implemented by the JDK implementations of Collection, like ArrayList. This is inherent to how object oriented programming works; if you call a method of an object where you only know one of it's interfaces, it will still call the method of the fully implemented class.
Neither the Collection nor List interface provide an implementation for the iterate() method, so this implementation must come from the run-time type of the object you're iterating over. So yes, the collection will iterate in a predictable order if you use an ordered list.
Hey guys I've been teaching myself java and I working on this assignment.
http://ljing.org/games/focus/
So I write a Linked list from scratch, I write a Deque class using the LinkedList class
But!
There's only one question I don't understand about the classes Iterator.
I just don't understand what does the Class Deque Iterator is supposed to do.
Also, I have this in my code:
class Deque<Item> implements Iterable<Item>.
But then the compiler complains that in my Deque class I need to override a method
#Override
public Iterator<Item> iterator()
{
throw new UnsupportedOperationException("Not supported yet.");
}
But I don't understand why
There are two different interfaces in Java for iteration that are important, Iterable and Iterator. They each serve a different purpose.
Iterable
When something implements this interface, this means that it can be iterated on. This is useful for us because Java gives us a shortcut for iterating over things that implement Iterable using a for-each loop:
List<String> elements = ... ; // List is an instance of Iterable
for (String element : elements)
System.out.println(element);
Anything that is an instance of Iterable can be used in a for-each loop. If you have your own custom MyDeque class that implements Iterable, then you can use that in a for-each as well:
MyDeque<String> elements = ... ;
for (String element : elements)
System.out.println(element);
This brings us to...
Iterator
This interface is how the iteration is actually performed. The for-each loop compiles to something like this:
MyDeque<String> elements = ... ;
for (Iterator<String> $iter = elements.iterator(); $iter.hasNext();) {
String element = $iter.next();
System.out.println(element);
}
This piece of code is functionally equivalent to the for-each above. hasNext() is the continuation condition (do I have more stuff to give you?) and next() actually gives you the next element, or throws a NoSuchElementException if we don't have anything else.
The point of making your custom deque implement Iterable is just to make it so you can iterate over the elements in your deque using something like a for loop. Its Iterator implementation is the thing that will let you actually do that iteration.
An iterator is a concept for accessing the elements in a collection. Because you say implements Iterable<Item>, you tell the compiler that you provide this mechanism of accessing the elements of your Deque. But that's not enough yet. Besides claiming you will do it, you actually have to do it. In this case, doing it is implementing the method.
What happens if you don't:
Because you told the compiler you would provide this, you have to implement the method iterator(), which is part of this access concept. If you do not implement the method, the compiler complains and tells you "hey, you said you would do it. So keep your word!".
There are two ways to solve this:
1.) In the first place, don't give your word you would provide the access concept through an iterator - remove implements Iterable<Item>
2.) Keep your word and implement the method. You will have to write an own Iterator class for this. That's a rather short task once you know what to do.
The question might be pretty vague I know. But the reason I ask this is because the class must have been made with some thought in mind.
This question came into my mind while browsing through a few questions here on SO.
Consider the following code:
class A
{
private int myVar;
A(int varAsArg)
{
myVar = varAsArg;
}
public static void main(String args[])
{
List<A> myList = new LinkedList<A>();
myList.add(new A(1));
myList.add(new A(2));
myList.add(new A(3));
//I can iterate manually like this:
for(A obj : myList)
System.out.println(obj.myVar);
//Or I can use an Iterator as well:
for(Iterator<A> i = myList.iterator(); i.hasNext();)
{
A obj = i.next();
System.out.println(obj.myVar);
}
}
}
So as you can see from the above code, I have a substitute for iterating using a for loop, whereas, I could do the same using the Iterator class' hasNext() and next() method. Similarly there can be an example for the remove() method. And the experienced users had commented on the other answers to use the Iterator class instead of using the for loop to iterate through the List. Why?
What confuses me even more is that the Iterator class has only three methods. And the functionality of those can be achieved with writing a little different code as well.
Some people might argue that the functionality of many classes can be achieved by writing one's own code instead of using the class made for the purpose. Yes,true. But as I said, Iterator class has only three methods. So why go through the hassle of creating an extra class when the same job can be done with a simple block of code which is not way too complicated to understand either.
EDIT:
While I'm at it, since many of the answers say that I can't achieve the remove functionality without using Iterator,I would just like to know if the following is wrong, or will it have some undesirable result.
for(A obj : myList)
{
if(obj.myVar == 1)
myList.remove(obj);
}
Doesn't the above code snippet do the same thing as remove() ?
Iterator came long before the for statement that you show in the evolution of Java. So that's why it's there. Also if you want to remove something, using Iterator.remove() is the only way you can do it (you can't use the for statement for that).
First of all, the for-each construct actually uses the Iterator interface under the covers. It does not, however, expose the underlying Iterator instance to user code, so you can't call methods on it.
This means that there are some things that require explicit use of the Iterator interface, and cannot be achieved by using a for-each loop.
Removing the current element is one such use case.
For other ideas, see the ListIterator interface. It is a bidirectional iterator that supports inserting elements and changing the element under the cursor. None of this can be done with a for-each loop.
for(A obj : myList)
{
if(obj.myVar == 1)
myList.remove(obj);
}
Doesn't the above code snippet do the same thing as remove() ?
No, it does not. All standard containers that I know of will throw ConcurrentModificationException when you try to do this. Even if it were allowed to work, it is ambiguous (what if obj appears in the list twice?) and inefficient (for linked lists, it would require linear instead of constant time).
The foreach construct (for (X x: list)) actually uses Iterator as its implementation internally. You can feed it any Iterable as a source of elements.
And, as others already remarked: Iterator is longer in Java than foreach, and it provides remove().
Also: how else would you implement your own provider class (myList in your example)? You make it Iterable and implement a method that creates an Iterator.
For one thing, Iterator was created way before the foreach loop (shown in your code sample above) was introduced into Java. (The former came in Java2, the latter only in Java5).
Since Java5, indeed the foreach loop is the preferred idiom for the most common scenario (when you are iterating through a single Iterable at a time, in the default order, and do not need to remove or index elements). Note though that the foreach uses an iterator in the background for standard collection classes; in other words it is just syntactic sugar.
Iterator, listIterator both are used to allow different permission to user, like list iterator have 9 methods but iterator have only 3 methods, but have remove functionality which you can't achieve with for loop. Enumeration is another thing which is also used to give only read permissions.
Iterator is an implementation of the classical GoF design pattern. In that way you can achieve clear behaviour separation from the 'technical code' which iterates (the Iterator) and your business code.
Imagine you have to change the 'next' behaviour (say, by getting not the next element but the next EVEN element). If you rely only on for loops you will have to change manually every single for loop, in a way like this
for (int i; i < list.size(); i = i+2)
while if you use an Iterator you can simply override/rewrite the "next()" and "hasNext()" methods and the change will be visible everywhere in your application.
I think answer to your question is abstraction. Iterator is written because to abstract iterating over different set of collections.
Every collection has different methods to iterate over their elements. ArrayList has indexed access. Queues has poll and peek methods. Stack has pop and peek.
Usually you only need to iterate over elements so Iterator comes into play. You do not care about which type of Collection you need to iterate. You only call iterator() method and user Iterator object itself to do this.
If you ask why not put same methods on Collection interface and get rid of extra object creation. You need to know your current position in collection so you can not implement next method in Collection because you can not use it on different locations because every time you call next() method it will increment index (simplifying every collection has different implementation) so you will skip some objects if you use same collection at different places. Also if collection support concurrency than you can not write a multi-thread safe next() method in collection.
It is usually not safe to remove an object from collection iterating by other means than iterator. Iterator.remove() method is safest way to do it. For ArrayList example:
for(int i=0;i
I have one list:
List<Object> myList = new ArrayList<Object>();
To get from this list there are two methods:
1.
for(Object obj : myList )
{
// some code
}
2.
Iterator<Object> objIt = myList.iterator();
while(obj.hasNext()) {
Object obj = (Object)objIt.next();
// some code
}
My question is which one is memory efficient and iterates fast?
They do the same thing - the enhanced for loop is just syntactic sugar for the longhand version (for iterables; for arrays it's slightly different). Unless you need the iterator explicitly (e.g. to call remove()) I'd use the first version.
See section 14.14.2 of the Java Language Specification for more details of the exact transformation performed by the compiler.
Using an Iterator provides much safer access to the List from outside the defining class as you cannot accidentally override the entire List for example. You can only ever access one element at a time: the top one.
So the guideline we use is to only use the for each approach inside the defining class and whenever the List needs to be accessed from the outside an iterator has to be used. This also enforces the concept of keeping the logic of how to modify a member inside the class that contains it. All complex operations that are needed outside have to be implemented in public methods inside that class.
Iterator : It gives you the result when needed and don't gets all the result in-memory
The first one is what you call an "enhanced for loop" which was introduced in JDK 1.5+
It is more convenient way of iterating through a list. Also, you do not need to do explicit castings if you are using that.
From the performance perspective, I don't think there isn't much difference between the two.
Enhanced for loop used iterator only inside it. So both are same.
First one is more clear, but if you want to remove elements while visiting the list your only choice is an iterator.