I need to iterate all the elements of ArrayList except the last one. So I want to create such iterator. But I don't what to implement the whole iterator, I need to override only the hasNext() method, so I would like to subclass a "standard" iterator. Is there any way to do that?
I think the better way to do that rather than overriding the default iterator is to iterate the ArrayList on your own. An ArrayListhas a couple of method defined that can help you accomplish the task: get(int) and size().
Everything you have to do is to get the total number of elements in the ArrayList(with size()) and then loop through the elements accessing each element directly in each iteration using the get() method. Your code would look something like this:
for(int i = 0; i < myList.size() - 1; i++){
element = myList.get(i);
//do something
}
Now with this principle in mind, you may create your own class to iterate the ArrayList.
It would be odd to modify the iterator to perform this traversal. The obvious thing to do is to write the "algorithm" as you want it:
public static <T> void eachExceptLast(List<? extends T> list, Operation<T> op) {
Iterator<T> iter = list.iterator();
if (!iter.hasNext()) {
return;
}
T item = iter.next();
while (iter.hasNext()) {
op.run(item);
item = iter.next();
}
}
(Or use an index assuming a RandomAccess list.)
However, there's a much better way of doing this. list.subList(0, list.size()-1) (for a non-empty list) will return a view of the original list less the last element. It doesn't do a copy, and you can even use Iterator.remove.
You can create a class that implements either the Iterator or ListIterator interfaces and then override the hasNext() method .
Related
I want to start at the end of the list and iterate it using ListIterators previous method
public void add(E obj) {
ListIterator <E> iter = theList.listIterator();
while (iter.hasNext()) {
if (obj.compareTo(iter.next()) < 0) {
iter.previous();
iter.add(obj);
return;
}
}
iter.add(obj);
}
Every time I run my test class it iterators from the beginning.
to get iterator in reverse order use method list.listIterator(int index)
this method will return iterator from specified position,
you should put size of list means last element index.
after that you can use hasPrevious() and previous() method.
this will work,
// declare arraylist
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}
ListIterator, like all Iterators, always start at the beginning. The previous method allows for less constrained movement, but it still starts at the beginning. You overall intent is unclear, so it's possible you're coming at this the wrong way, but the most straightforward way for you would be to reorder the list first and then do your iteration.
UPDATE Nevermind, Rajj has it.
I need to figure out the number of elements in an Iterable in Java.
I know I can do this:
Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
it.next();
sum++;
}
I could also do something like this, because I do not need the objects in the Iterable any further:
it = values.iterator();
while (it.hasNext()) {
it.remove();
sum++;
}
A small scale benchmark did not show much performance difference, any comments or other ideas for this problem?
TL;DR: Use the utility method Iterables.size(Iterable) of the great Guava library.
Of your two code snippets, you should use the first one, because the second one will remove all elements from values, so it is empty afterwards. Changing a data structure for a simple query like its size is very unexpected.
For performance, this depends on your data structure. If it is for example in fact an ArrayList, removing elements from the beginning (what your second method is doing) is very slow (calculating the size becomes O(n*n) instead of O(n) as it should be).
In general, if there is the chance that values is actually a Collection and not only an Iterable, check this and call size() in case:
if (values instanceof Collection<?>) {
return ((Collection<?>)values).size();
}
// use Iterator here...
The call to size() will usually be much faster than counting the number of elements, and this trick is exactly what Iterables.size(Iterable) of Guava does for you.
If you are working with java 8 you may use:
Iterable values = ...
long size = values.spliterator().getExactSizeIfKnown();
it will only work if the iterable source has a determined size. Most Spliterators for Collections will, but you may have issues if it comes from a HashSetor ResultSetfor instance.
You can check the javadoc here.
If Java 8 is not an option, or if you don't know where the iterable comes from, you can use the same approach as guava:
if (iterable instanceof Collection) {
return ((Collection<?>) iterable).size();
} else {
int count = 0;
Iterator iterator = iterable.iterator();
while(iterator.hasNext()) {
iterator.next();
count++;
}
return count;
}
This is perhaps a bit late, but may help someone. I come across similar issue with Iterable in my codebase and solution was to use for each without explicitly calling values.iterator();.
int size = 0;
for(T value : values) {
size++;
}
You can cast your iterable to a list then use .size() on it.
Lists.newArrayList(iterable).size();
For the sake of clarity, the above method will require the following import:
import com.google.common.collect.Lists;
Strictly speaking, Iterable does not have size. Think data structure like a cycle.
And think about following Iterable instance, No size:
new Iterable(){
#Override public Iterator iterator() {
return new Iterator(){
#Override
public boolean hasNext() {
return isExternalSystemAvailble();
}
#Override
public Object next() {
return fetchDataFromExternalSystem();
}};
}};
java 8 and above
StreamSupport.stream(data.spliterator(), false).count();
I would go for it.next() for the simple reason that next() is guaranteed to be implemented, while remove() is an optional operation.
E next()
Returns the next element in the iteration.
void remove()
Removes from the underlying collection the last element returned by the iterator (optional operation).
As for me, these are just different methods. The first one leaves the object you're iterating on unchanged, while the seconds leaves it empty.
The question is what do you want to do.
The complexity of removing is based on implementation of your iterable object.
If you're using Collections - just obtain the size like was proposed by Kazekage Gaara - its usually the best approach performance wise.
Why don't you simply use the size() method on your Collection to get the number of elements?
Iterator is just meant to iterate,nothing else.
Instead of using loops and counting each element or using and third party library we can simply typecast the iterable in ArrayList and get its size.
((ArrayList) iterable).size();
Is it advisable not to use iterator.hasNext() in looping over an iterator?
For example I would like to set value obj to each element of a list. I could use the following code or make it more readable by using hasNext() in a loop.
int size = list.size();
ListIterator<? super T> itr = list.listIterator();
for (int i=0; i<size; i++) {
itr.next();
itr.set(obj);
}
Instead of these lines I could write my code like the following.
for (ListIterator<? super T> itr = list.listIterator(); itr.hasNext(); ) {
itr.next();
itr.set(obj);
}
Is it advisable not to use iterator.hasNext() in looping over an iterator?
Um, no. hasNext is the standard way you iterate with an iterator. That's what the enhanced-for statement does behind the scenes for an iterable, for example.
Having said that, your code is already ListIterator-specific, as you're using ListIterator.set - so your second block of code won't actually compile at the moment. Even if it did, it wouldn't work, as you still need to call next(). This would work though:
for (ListIterator<? super T> itr = list.listIterator(); itr.hasNext(); ) {
itr.next();
itr.set(obj);
}
Well, when NetBeans refactor you for-each loop to use of iterators, they do it in following way.
for-each:
for (T object : list) {
}
iterator pattern:
for (Iterator<T> it = list.iterator(); it.hasNext();) {
T object = it.next();
}
I think it is totally okay to use hasNext() on iterator while iterating.
There is no such recommendation not to use hasNext.
The Iterator API list has just three methods, add, remove and hasNext
Also from clean code the second approach looks far better then the first one.
When using an iterator, you should always call the hasNext() method. Otherwise, you may run into a NoSuchElementException when calling the next() method.
Of course, you should use hasNext(), but only for iterating over a collection, not for populating the collection. To fill the collection, work on the collection itself, not on it's iterator and to read from the collection use the for loop as described by #JMelnik.
Fill the collection
Collection<MyObject> list = ...;
while (something) {
list.add(myObject);
}
Read the collection
for (MyObject myObject : list) {
...
}
I am new in Java and I'm really confused with iterator and iterable. Can anyone explain to me and give some examples?
An Iterable is a simple representation of a series of elements that can be iterated over. It does not have any iteration state such as a "current element". Instead, it has one method that produces an Iterator.
An Iterator is the object with iteration state. It lets you check if it has more elements using hasNext() and move to the next element (if any) using next().
Typically, an Iterable should be able to produce any number of valid Iterators.
An implementation of Iterable is one that provides an Iterator of itself:
public interface Iterable<T>
{
Iterator<T> iterator();
}
An iterator is a simple way of allowing some to loop through a collection of data without assignment privileges (though with ability to remove).
public interface Iterator<E>
{
boolean hasNext();
E next();
void remove();
}
See Javadoc.
I will answer the question especially about ArrayList as an example in order to help you understand better..
Iterable interface forces its subclasses to implement abstract method 'iterator()'.
public interface Iterable {
...
abstract Iterator<T> iterator(); //Returns an 'Iterator'(not iterator) over elements of type T.
...
}
Iterator interface forces its subclasses to implement abstract method 'hasNext()' and 'next()'.
public interface Iterator {
...
abstract boolean hasNext(); //Returns true if the iteration has more elements.
abstract E next(); //Returns the next element in the iteration.
...
}
ArrayList implements List, List extends Collection and Collection extends Iterable..
That is, you could see the relationship like
'Iterable <- Collection <- List <- ArrayList'
.
And Iterable, Collection and List just declare abstract method 'iterator()' and ArrayList alone implements it.
I am going to show ArrayList source code with 'iterator()' method as follows for more detailed information.
'iterator()' method returns an object of class 'Itr' which implements 'Iterator'.
public class ArrayList<E> ... implements List<E>, ...
{
...
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
...
public boolean hasNext() {
return cursor != size;
}
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
...
}
}
Some other methods or classes will iterate elements of collections like ArrayList through making use of Iterator (Itr).
Here is a simple example.
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String string = iterator.next();
System.out.println(string);
}
}
Now, is it clear? :)
I know this is an old question, but for anybody reading this who is stuck with the same question and who may be overwhelmed with all the terminology, here's a good, simple analogy to help you understand this distinction between iterables and iterators:
Think of a public library. Old school. With paper books. Yes, that kind of library.
A shelf full of books would be like an iterable. You can see the long line of books in the shelf. You may not know how many, but you can see that it is a long collection of books.
The librarian would be like the iterator. He can point to a specific book at any moment in time. He can insert/remove/modify/read the book at that location where he's pointing. He points, in sequence, to each book at a time every time you yell out "next!" to him. So, you normally would ask him: "has Next?", and he'll say "yes", to which you say "next!" and he'll point to the next book. He also knows when he's reached the end of the shelf, so that when you ask: "has Next?" he'll say "no".
I know it's a bit silly, but I hope this helps.
If a collection is iterable, then it can be iterated using an iterator (and consequently can be used in a for each loop.) The iterator is the actual object that will iterate through the collection.
The most important consideration is whether the item in question should be able to be traversed more than once. This is because you can always rewind an Iterable by calling iterator() again, but there is no way to rewind an Iterator.
Implementing Iterable interface allows an object to be the target of the "foreach" statement.
class SomeClass implements Iterable<String> {}
class Main
{
public void method()
{
SomeClass someClass = new SomeClass();
.....
for(String s : someClass) {
//do something
}
}
}
Iterator is an interface, which has implementation for iterate over elements. Iterable is an interface which provides Iterator.
As explained here, The “Iterable” was introduced to be able to use in the foreach loop. A class implementing the Iterable interface can be iterated over.
Iterator is class that manages iteration over an Iterable. It maintains a state of where we are in the current iteration, and knows what the next element is and how to get it.
Consider an example having 10 apples.
When it implements Iterable, it is like putting each apple in boxes from 1 to 10 and return an iterator which can be used to navigate.
By implementing iterator, we can get any apple, apple in next boxes etc.
So implementing iterable gives an iterator to navigate its elements although to navigate, iterator needs to be implemented.
Question:Difference between Iterable and Iterator?
Ans:
iterable: It is related to forEach loop
iterator: Is is related to Collection
The target element of the forEach loop shouble be iterable.
We can use Iterator to get the object one by one from the Collection
Iterable present in java.ḷang package
Iterator present in java.util package
Contains only one method iterator()
Contains three method hasNext(), next(), remove()
Introduced in 1.5 version
Introduced in 1.2 version
Basically speaking, both of them are very closely related to each other.
Consider Iterator to be an interface which helps us in traversing through a collection with the help of some undefined methods like hasNext(), next() and remove()
On the flip side, Iterable is another interface, which, if implemented by a class forces the class to be Iterable and is a target for For-Each construct.
It has only one method named iterator() which comes from Iterator interface itself.
When a collection is iterable, then it can be iterated using an iterator.
For understanding visit these:
ITERABLE: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Iterable.java
ITERATOR http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Iterator.java
Iterable were introduced to use in for each loop in java
public interface Collection<E> extends Iterable<E>
Iterator is class that manages iteration over an Iterable. It maintains a state of where we are in the current iteration, and knows what the next element is and how to get it.
In addition to ColinD and Seeker answers.
In simple terms, Iterable and Iterator are both interfaces provided in Java's Collection Framework.
Iterable
A class has to implement the Iterable interface if it wants to have a for-each loop to iterate over its collection. However, the for-each loop can only be used to cycle through the collection in the forward direction and you won't be able to modify the elements in this collection. But, if all you want is to read the elements data, then it's very simple and thanks to Java lambda expression it's often one liner. For example:
iterableElements.forEach (x -> System.out.println(x) );
Iterator
This interface enables you to iterate over a collection, obtaining and removing its elements. Each of the collection classes provides a iterator() method that returns an iterator to the start of the collection. The advantage of this interface over iterable is that with this interface you can add, modify or remove elements in a collection. But, accessing elements needs a little more code than iterable. For example:
for (Iterator i = c.iterator(); i.hasNext(); ) {
Element e = i.next(); //Get the element
System.out.println(e); //access or modify the element
}
Sources:
Java Doc Iterable
Java Doc Iterator
An anonymous class easily converts an Iterator to an Iterable and lets you use the Iterable syntax (for loops, forEach()).
Example: consider an Iterator<T> it
for (T element : new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return it;
}
}) {
//do something with `T element`
}
Abstracted in a function
static <T> Iterable<T> toIterable(Iterator<T> it) {
return new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return it;
}
};
}
Usage
for (T element: toIterable(it) {
...
}
Most java interfaces ends with 'able'. examples are Iterable, Cloneable, Serializable, Runnable, etc. Therefore, Iterable is an interface that has an abstract method called iterator() which returns an Iterator object.
public interface Iterable {
abstract Iterator<T> iterator();
}
Iterator interface has abstract method 'hasNext()' and 'next()'.
public interface Iterator {
abstract boolean hasNext();
abstract E next();
}
A clear use is a List which extends->Collections Interface->extends Iterable
List<String> countrylist = new ArrayList<>();
list.add("US");
list.add("China");
list.add("Japan");
list.add("India");
Iterator<String> it = countrylist.iterator();
while (it.hasNext()) {
String string = it.next();
System.out.println(string);
}
I have an Iterator that I use on a HashMap, and I save and load the iterator.
is there a way to get the previous key in the HashMap with Iterator? (java.util.Iterator)
Update
I save it as an attribute in a Red5 connection and then load it back to continue working where i stopped.
Another update
I'm iterating through the keyset of the HashMap
You can use ListIterator instead of Iterator.
ListIterator has previous() and hasPrevious() methods.
Not directly, as others pointed out, but if you e.g. need to access one previous element you could easily save that in a separate variable.
T previous = null;
for (Iterator<T> i = map.keySet().iterator(); i.hasNext();) {
T element = i.next();
// Do something with "element" and "previous" (if not null)
previous = element;
}
It sounds like you want the array semantics more akin to a ListIterator rather than those provided by the Iterator interface. The easiest way to acquire such a thing is likely to construct a list ( from the key-set (LinkedList<K> keyList = new LinkedList<K>(map.keySet())), then use a ListIterator manually instead of a regular Iterator or foreach.
For very simple cases of needing to remember consecutive items, the simplest way to handle this is to store the previous Key in a local variable and update it at the end of the loop.
No, an Iterator<E> defines only 3 methods:
boolean hasNext()
E next()
void remove()
You can of course implement your own iterator.
As others have said, you only access an element using next(). However it's sort of a matter of terminology. Once you call next() this is the current element.
Unless the problem is you need to see two consecutive items in the collection each iteration, in which case a simple variable would seem easiest.
Although Set doesn't provide a method for a reverse iterator, Deque does. You can use descendingIterator() for an iterator in reverse order and iterator(), for an iterator in forwards order.
(You can create a Deque from a Set via Deque<T> deque = new LinkedList<T>(set), where set is your Set and T the generic type you're using.)
Ultimately Iterators are not fully suited for your task.
Why not create a List from your Set (via, eg, List list = new LinkedList(set)) and iterate by using a standard indexed for-loop? That way you know the previous element is at i - 1.
using iterator, No you dont have an option to get a previous key value. it has only hasNext() and next() methods.
No, you can't. The Iterator interface has no method to get the previous element.
But what you can do is - a little bit rubbish- creating a List<Entry<Integer, YourObjectType>> where the Integer-value represents the hash-code of the key-object. Then you can do something like this:
for (int i = 0; i < list.size(); i++)
{
YourObjectType current = list.get(i).getValue();
YourObjectType previous = (i == 0 ? null : list.get(i - 1).getValue());
// Do whatever you want
}
I know this is very rubbish, but it is possible
Make your own Iterator:
public class EnhancedIterator<E> implements Iterator<E>{
private List<E> list;
private int indexSelected=-1;
public EnhancedIterator(List<E> list){
this.list=list;
}
#Override
public boolean hasNext() {
return indexSelected<list.size()-1;
}
#Override
public E next() {
indexSelected++;
return current();
}
#Override
public void remove() {
list.remove(indexSelected);
}
public void remove(int i){
list.remove(i);
if(i<indexSelected){
indexSelected--;
}
}
public E previous(){
indexSelected--;
return current();
}
public E current(){
return list.get(indexSelected);
}
public E get(int i){
return list.get(i);
}
}