Lets talk about:
- For-each loop over a Map
- Control over for-each loops (index/remove)
At first, I asked myself if it's possible to obtain those targets just by a simple code.?
It's not so clear for all, but answer is YES.
However, there are still some small languages changes that would improve programming quality.
Indexing control over for-each loops
What would be the effect of adding indexing directly to for-each loop?
- Language syntax need to be extended.
- While loop can iterate more than MAX_INT there might be possibility to obtain exception (IndexOutOfBoundsException)
- We will not be able to obtain some more complicated indexes (like even numbers, numbers started from 333, ...)
- It's higher probability that when people get used to it they will want a more complicated syntax
What is the impact of other solutions?
- Implement IntIterator, LongIterator
- Possible to extend for-each loop with increment (initialization) expression for (String s:array; intIterator.next()) { ... }
- We would be able to index everything
- No negative impact during extending loop statement
- We could selectively index elements
Sample:
* @author Marek Kozieł
*/
public interface IntIterator extends Serializable {
/*
* Returns <tt>true</tt> if the iteration has more elements. (In other words, returns <tt>true</tt> if <tt>next</tt> would return an element rather than throwing an exception.)
*
* @return <tt>true</tt> if the iterator has more elements.
*/
public boolean hasNext();
/*
* Returns the next element in the iteration.
*
* @return the next element in the iteration.
* @exception NoSuchElementException iteration has no more elements.
*/
public int next();
public static class IntIteratorImpl implements IntIterator {
public IntIteratorImpl() {
last = 0 - 1;
}
public IntIteratorImpl(int starValue) {
if (starValue == Integer.MIN_VALUE) { throw new IllegalArgumentException("Start value(" + starValue + ") is unsupported"); }
last = starValue - 1;
}
private int last = 0;
@Override
public final boolean hasNext() {
return (last != Integer.MAX_VALUE);
}
@Override
public final int next() {
if (last == Integer.MAX_VALUE) { throw new NoSuchElementException(); }
return (last++);
}
}
}
Removing control over for-each loops
What would be the effect of adding indexing directly to for-each loop?
- Possible, but for loop should know if it's iterate through Iterator.
- Syntax need to be extended like:
for.remove(...).
What is the impact of another solutions?
Allow for-each loop to iterate through Iterator not only through Iterable!
- Will allow use more complicated Iterators!
- Container would be able to return easily few iterators (Map iterator over: keys, values, distinct values, keys & values ) without complicated objects structure.
- No syntax change is required!
For-each loop over a Map
What would be the effect of allowing loop to work on Map-s?
- Language would become dependent from Map implementation
- Syntax need to be extended!
What is the impact of another solution?
I personally use solution that allow me to iterate through my own Map-s for a few months. Container is just able to return a few different iterators (see previous solution).
Summary
- Language changes can have high negative impact.
- Making language dependent from one implementation will skip people from implemending better ones.
Another sugestion: Allow for-each loop iterator through more than one container
Effect:
- Syntax need to be extended:
for(String s: array,collection,iterator)
if (for.current==array) { ... } - Skipping people from writing a few loops with the same content!
For-each loop over a Map
ReplyDeleteYou already have this in Java:
for(Map.Entry e : map.entrySet()) {
// do something with e.getKey() and e.getValue()
}
Indexing control over for-each loops
Why do you need this indexing? Perhaps to copy data between array and collection. So better instead of array, use ArrayList.
Removing control over for-each loops
Yes, this can be disappointing. I had for(E e : collection), then I noticed that I need removal there. Do I need to change it to for(Iterator<E> it = collection.iterator(); it.hasNext(); ){E e = it.next .... Code is much less readable. But this can be easily done without any language extensions:
IterableHelper<E> helper = IterableHelper.create(collection);
for(E e : helper) {
...
helper.remove();
...
}
Another sugestion: Allow for-each loop iterator through more than one container
I can't remember if I ever needed it in my programming experience - no need to add it to Java if it's almost never used. But you can create a special method for this:
interface F<E> { void f(E e){} }
...
Utils.forEach(new F<E>() {
void f(E e) {
...
}
}, collection1, collection2, ...);
A lot more typing, but it's not a problem. As I wrote, it happens very rarely. This way you can do other tasks that would otherwise require duplicating of your code.
>For-each loop over a Map
ReplyDeletePersonally, I do not use maps at all, but maybe people do not know this solution.
>Why do you need this indexing?
I've already said that I'm against of indexing in loop.
Almost all developers know about Map.entrySet() and use it to iterate map.
ReplyDelete>Almost all developers know about Map.entrySet() and use it to iterate map.
ReplyDeleteIt's not about possibility, I just do not like the logics according to which it's done like that.