forEach/forEachOrdered/forEachRemaining ... iterate?
Peter Levart
peter.levart at gmail.com
Thu Jun 13 07:47:36 PDT 2013
I know it's a little late, but let's look at current situation. There
are 5 methods in current APIs with similar names and signatures + 1
additional with a little different signature in Map + some similarly
named methods in ConcurrentHashMap:
interface Stream<T> {
void forEach(Consumer<? super T> action)
void forEachOrdered(Consumer<? super T> action)
}
interface Iterable<T> {
void forEach(Consumer<? super T> action)
}
interface Iterator<T> {
void forEachRemaining(Consumer<? super T> action)
}
interface Spliterator<T> {
void forEachRemaining(Consumer<? super T> action)
}
interface Map<K, V> {
void forEach(BiConsumer<? super K, ? super V> action)
}
class ConcurrentHashMap<K, V> ... {
void forEachKey(long parallelismThreshold,
Consumer<? super K> action)
<U> void forEachKey(long parallelismThreshold,
Function<? super K, ? extends U> transformer,
Consumer<? super U> action)
void forEachValue(long parallelismThreshold,
Consumer<? super V> action)
<U> void forEachValue(long parallelismThreshold,
Function<? super V, ? extends U> transformer,
Consumer<? super U> action)
}
I'm wondering if the following alternative would be easier to read and
reason-about in code:
interface Stream<T> {
void forEach(Consumer<? super T> action)
void iterate(Consumer<? super T> action)
}
interface Iterable<T> {
void iterate(Consumer<? super T> action)
}
interface Iterator<T> {
void iterateRemaining(Consumer<? super T> action)
}
interface Spliterator<T> {
void iterateRemaining(Consumer<? super T> action)
}
interface Map<K, V> {
void iterate(BiConsumer<? super K, ? super V> action)
}
class ConcurrentHashMap<K, V> ... {
void forEachKey(long parallelismThreshold,
Consumer<? super K> action)
<U> void forEachKey(long parallelismThreshold,
Function<? super K, ? extends U> transformer,
Consumer<? super U> action)
void forEachValue(long parallelismThreshold,
Consumer<? super V> action)
<U> void forEachValue(long parallelismThreshold,
Function<? super V, ? extends U> transformer,
Consumer<? super U> action)
}
Why? I'm a little concerned about the duality of Stream.forEach() and
Iterable.forEach(). While the later is always sequential and
encounter-ordered, the former can be executed out-of order and/or
in-parallel. I think that by naming the sequential variants differently,
the reader of code need not be concerned about the type of the target
that the method is invoked upon, just the name. This enables fast
browsing of code where the eye can quickly glance over iterate()s but
slows down on each forEach()...
How do others feel about the (re)use of forEach... names in different
APIs? Would it be more difficult to find the right method if iterate()
was used instead of forEach() for iteration?
Regards, Peter
More information about the lambda-dev
mailing list