Enhance Map, List, and Set such that these interfaces extend Function, IntFunction, and Predicate, respectively
Ralf Spöth
ralf.spoeth at gmail.com
Thu Sep 15 15:19:35 UTC 2022
Dear all,
I just stumbled about some frequent uses of collections as filters and mapping functions, and I am wondering whether it's possible to enhance the core collection interfaces Map, List, and Set:
(please forgive lousy syntax hereinafter)
interface Map<K, V> extends Function<K, V> {
default V apply(K k) {return get(k);}
}
interface List<T> extends IntFunction<T> {
default T apply(int index) { return get(I);}
}
interface Set<T> extends Predicate<T> {
default boolean test(T t) {return contains(t);}
}
The cost of extending existing interfaces in widespread use may be prohibitive, plus you may find the value proposition not very convincing.
The interpretation of a Map as a Function feels very natural, although the use of the given map in a stream is also straightforward:
Stream.of(1, 2).map(Map.of(1, "One", 2, "Two")::get).toList(); // ["One", "Two"]
Assigning the map to a function variable is a little more demanding:
// var m = Map.of(...)::get; compiler error
Function<Integer, String> m = Map.of(1, "One")::get; // WORKS
Since we enjoy the pleasures of local variable type inference, this is a little awkward.
If a map were a function, then we might write instead:
var m = Map.of(1, "One", 2, "Two");
Stream.of(1, 2).map(m).toList(); // ["One", "Two"]
The interpretation of a list as a function of an index may seem a little more far-fetched:
var l = List.of("One", "Two", "Three");
IntStream.range(0, l.size()).filter(i -> i%2==0).mapToObj(l::get).toList(); // ["One", "Three"];
The test for inclusion in a set is a common operation and is therefore a frequent candidate for filters in stream operations.
var primes = Set.of(2, 3, 5, 7);
IntStream.range(5, 10).filter(primes::contains).toArray(); // [5, 7]
With Set implementing Predicate and List implementing IntFunction we may write:
var primes = Set.of(2, 3, 5, 7);
var elems = List.of("One", "Two", "Three", "Four");
IntStream.range(0, 5).filter(primes).mapToObj(elems).toList(); // ["Three", "Four"]
Arguably,
IntStream.range(0, 5).filter(primes::contains).mapToObj(elems::get).toList();
is not too bad as well…
Just an idea...
Thanks for reading!
- Ralf
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/java-se-spec-comments/attachments/20220915/ebdaa596/attachment.htm>
More information about the java-se-spec-comments
mailing list