private SomeObject[] all_objs;
public Iterator<SomeObject> iterator() {
//
}
What is the best way to get an iterator from an array of SomeObject?
EDIT
So there is no way to generate iterator without using the wrappers like ArrayLists or HashSets ?
You could write your own class that implements Iterator<SomeObject>. Simply implement the methods of the interface. If you don't want the users of the iterator from removing items from the array (since it isn't an ArrayList), then throw an UnsupportedOperationException if this method is called.
Of course if you use an ArrayList<SomeObject> then the iterator() method would only have to return the iterator from the ArrayList making your life much easier.
Using the List iterator:
import java.util.List;
import java.util.Arrays;
public <T> Iterator<T> iterator() {
List<T> list = (List<T>) Arrays.asList(all_objs);
return list.iterator();
}
You can also look at the code of java.util.ArrayList. Here is how you should implement it.
T=SomeObject //Your Class
public YourIterable<T> implements Iterable<T>{
//**Iterable** Implementing this interface allows an object
//to be the target of the "foreach" statement.
public Iterator<T> iterator() {
return new Itr();
}
private class Itr implement Iterator<T> {
//Complex Implementation - You have to maintain a Cursor to keep track of
// which record was accessed
boolean hasNext() {
//Returns true if the iteration has more elements.
}
T next() {
//Returns the next element in the iteration.
}
void remove() {//Remove
}
}
}
Related
Does anyone know why can we loop through the "this" keyword here (in the subsetOf method)? To my knowledge this represents a JAVA object. Some extensive explanations are welcomed, would like to know why "this" can work in this way.
public class ArrayListSet<E> implements Set<E> {
private ArrayList<E> elements;
public ArrayListSet() {
elements = new ArrayList<>();
}
#Override
public void add(E e) {
if (!elements.contains(e))
elements.add(e);
}
#Override
public void remove(E e) {
elements.remove(e);
}
#Override
public boolean contains(Object e) {
return elements.contains(e);
}
#Override
public int size() {
return elements.size();
}
#Override
public boolean subsetOf(Set<?> other) {
for (E e : this) {
if (!other.contains(e))
return false;
}
return true;
}
}
You are declaring a class which implements the Set interface which itself extends the Iterable through the Collection interface. Any Object which is an implementation of the Iterable interface can be used inside a for-each loop.
So the inheritance hierarchy is this for your class:
Iterable
^
|
Collection
^
|
Set
^
|
ArrayListSet
Also the this keyword always refers to the current instance. In your code when you execute the subsetOf() the this will point to an instance of ArrayListSet (which was used to invoke the subSetOf() method) which is a type of Iterable through inheritance, so you can use it in a for-each loop.
Also since you are implementing a Set you need to supply an implementation of the Iterator<E> iterator(); method defined in the Set interface to make it an Iterable.
As implementations of the Iterable interface requires a iterator() method which returns an instance of the Iterator object. The Iterator Object will be used by the for-each loop to iterate over the elements of the ArrayListSet.
The implementation of the Iterator type returned from the iterator() method actually defines the iteration logic used by the for-each loop.
To use any Object in a for-each loop:
Step 1: Extend Iterable directly or through other Iterable types.
Step 2: Provide implementation of the Iterator iterator() method inherited from the Iterable interface.
Step 3: Implement an Iterator and return its instance from the iterator() method.
You can iterate through this since it represents a set. The set is iterable. Therefore it is valid syntax.
If I have a Map or a List and get an iterator from it, for example:
var map = new HashMap();
var iterator = map.entrySet().iterator();
if something modifies that map after the fact, will it affect the iterator or is the iterator basically immutable once created?
If it's not immutable, how to create an immutable iterator?
The only valid operations for an iterator are increment and dereference (although the Java Iterator combines the two in its next() method). If you have an unmodifiable iterator, that leaves you only dereferencing. The dereferencing can either give you an object reference, or it can be not valid to dereference because it does not refer to a valid position in the collection.
But those are the same semantics as Optional: an Optional can either be empty or have a valid object reference. So, create an Optional from the Iterator and use that as your "unmodifiable iterator":
private Optional<T> unmodifiableNext(Iterator<T> i)
{
if (i.hasNext()) {
return Optional.ofNullable(i.next());
} else {
return Optional.empty();
}
}
This has the additional benefit that the Optional is no longer tied to the collection, so the collection can be safely changed without changing which object the Optional refers to.
An iterator instance itself would not generally need the concept of mutability/immutability. However, the collection it is iterating over may be intended to be unmodifiable or immutable. Here is a way to disable the ability of an iterator to change the collection. If you return an instance of this class, then the remove() method of the returned iterator is disabled. The class is used by returning UnmodifiableIterator.create(yourIterator).
import java.util.Iterator;
/**
* UnmodifiableIterator, A wrapper around an iterator instance that
* disables the remove method.
*/
public final class UnmodifiableIterator<E> implements Iterator<E> {
/**
* iterator, The base iterator.
*/
private final Iterator<? extends E> iterator;
private UnmodifiableIterator(final Iterator<? extends E> iterator) {
this.iterator = iterator;
}
public static <E> Iterator<E> create(final Iterator<? extends E> iterator) {
if (iterator == null) {
throw new NullPointerException("The iterator can not be null.");
}
return new UnmodifiableIterator<>(iterator);
}
#Override
public boolean hasNext() {
return iterator.hasNext();
}
#Override
public E next() {
return iterator.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException("Iterator.remove() is disabled.");
}
}
I have many instance in code where a Collection, most usually a List is returned from a method and to account for the caller possibly altering that list, a defensive copy is made.
The JDK does not seem to provide a wrapper for this purpose, so I'm trying to roll my own (Note: java.util.concurrent.CopyOnWriteArrayList is not what I'm looking for here).
Schematically, what I'm trying is:
public class CopyOnWriteList<E> extends List<E> {
protected List<E> list;
protected boolean isCopied;
public CopyOnWriteList(List<E> list) {
this.list = list;
}
private void ensureCopy() {
if (!isCopied) {
list = new ArrayList<E>(list);
isCopied = true;
}
}
public E get(int i) {
return list.get(i);
}
public boolean add(E e) {
ensureCopy();
return list.add(e);
}
// ... many more simple methods
}
For most of the API this is simple enough, but looking at java.util.ArrayList I found, that for the method iterator() it returns a different implementation than for listIterator(), although is ListIterator extends its Iterator and it doesn't add any new members.
I wonder if there is a deeper reason behind this - I planned simply to implement iterator() and listIterator() all returning the same type of iterator - a ListIterator. Is there any logical reason why one should not return a ListIterator from the iterator()-method?
ListIterator extends Iterator. So if you return an object that implements ListIterator then it obviously also implements Iterator. But you also can decide to return different object that only implements Iterator, because the implementation could be more effective. The decision is up to you.
Set set = new HashSet();
set.add(1);
set.add(2)
Iterator iter = set.iterator(); // Wher hasnext been overrided
while(iter.hasnext()){
System.out.println(iter.next);
}
Iterator is an interface , set.iterator is returning the Iterator reference .
In HashSet(and its extended ,implemented classes) hasnext is nowhere overriden.
My doubt is where hasnext method is overriden(implemented) and how its linked in this context.
Thanks.
HashSet returns an implementation of Iterator, it doesn't implement Iterator itself. If you look at the source code of HashSet, you can see that it is actually backed by a HashMap:
public HashSet() {
map = new HashMap<E,Object>();
}
and when you call the iterator() method it is the iterator of this map that is returned:
public Iterator<E> iterator() {
return map.keySet().iterator();
}
This map in turn stores a KeySet...
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
Which in turn returns a KeyIterator when its iterator() method is invoked:
private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
and the HashIterator implements Iterator:
private abstract class HashIterator<E> implements Iterator<E>
So ultimately, the implementation of Iterator is a private subclass of HashIterator which is hidden away as an implementation detail hidden from clients. Such is the beauty of using interfaces!
You can see in the source of the HashSet that the iterator() method is implemented this way:
public Iterator<E> iterator() {
return map.keySet().iterator();
}
In the class AbstractHashedSet the iterator for keyset is implemented
/**
* KeySet iterator.
*/
protected static class KeySetIterator extends EntrySetIterator {
protected KeySetIterator(AbstractHashedMap parent) {
super(parent);
}
public Object next() {
return super.nextEntry().getKey();
}
}
So you have indeed an implementation.
I guess you should re-phrase your question if you experience a problem with the hasNext() method in your code.
HashSet implementation uses a HashMap so the iterator of HashSet is the iterator of the keySet of its HashMap... the keySet implementation of iterator is in AbstractMap class as seen here: AbstractMap-keySet
In the line
Iterator iter = set.iterator();
You are calling a method on Set which returns an instance of a class which implements the Iterator interface. It doesn't matter exactly what class is returned, all you need to care about is that it implements Iterator, hence implements the hasNext() method.
It's likely that the actual class is not part of the API and might change with different version of the JVM. The only thing you can be sure of is that it will implement Iterator.
Given a generic class:
class MyClass (
private List l = new LinkedList <String>();
public void addElement (String s) (l.add (s);)
.............
)
an accessor method that allows me to iterate on the list as it should be?
I had decided to implement a method that returns an iterator directly, but does not seem correct because it could change the list from the outside with remove ().
What do you think?
import java.util.*;
public Iterator<String> elements() {
return Collections.unmodifiableList(elements).iterator();
}
If you don't mind exposing the fact that the elements are stored as a List, you could also use do:
public ListIterator<String> elements() {
return Collections.unmodifiableList(elements).listIterator();
}
If you want to allow callers to use the "foreach" syntax, you might want to return an Iterable:
public Iterable<String> getElements() {
return Collections.unmodifiableList(elements);
}
And, again, if you don't mind exposing that the elements are returned as a List, this last solution could return List<String>
Most common way would be to implement Iterable interface but since you don't want to expose remove method you can follow the advice from NamshubWriter or provide your implementation of get(index) and size() methods (assuming your class should behave like a List). This will allow index based iteration.
however such a thing would be fine?
public Iterator<String> getList(){
return new Iterator<String>(){
Iterator<String> i=l.iterator();
public boolean hasNext() {
return i.hasNext();
}
public String next() {
if(!i.hasNext()) throw new NoSuchElementException();
return i.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
need a method that let me just browse the collection elements and preserve encapsulation, method unmodifiable ... I know but I can not use it.