StreamEx
, IntStreamEx
, LongStreamEx
and DoubleStreamEx
. To save the original interface, I had to write quite a few boring methods like the following: public class IntStreamEx implements IntStream { private final IntStream stream; @Override public <U> StreamEx<U> mapToObj(IntFunction<? extends U> mapper) { return new StreamEx<>(stream.mapToObj(mapper)); } ... }
IntStreamEx.of(random)
method). But then flows appeared that I can expand as I see fit. Below is a brief overview of the additional functionality..collect(Collectors.toSet())
or .collect(Collectors.toList())
. It looks verbose, even if you import the Collectors
statically. In StreamEx
I added methods toSet
, toList
, toCollection
, toMap
, groupingBy
with several signatures. The toMap
can toMap
function for keys if it is identity. A couple of examples: List<User> users; public List<String> getUserNames() { return StreamEx.of(users).map(User::getName).toList(); } public Map<Role, List<User>> getUsersByRole() { return StreamEx.of(users).groupingBy(User::getRole); } public Map<String, Integer> calcStringLengths(Collection<String> strings) { return StreamEx.of(strings).toMap(String::length); }
joining
methods also correspond to collectors, but before that the contents of the stream are passed through String::valueOf
: public String join(List<Integer> numbers) { return StreamEx.of(numbers).joining("; "); }
.filter(obj -> obj instanceof MyClass)
. However, this does not specify the type of stream, so you have to either manually type the elements or add one more step. .map(obj -> (MyClass)obj)
. When using StreamEx
this is done concisely using the select method: public List<Element> elementsOf(NodeList nodeList) { return IntStreamEx.range(0, nodeList.getLength()).mapToObj(nodeList::item).select(Element.class).toList(); }
select
method, by the way, the map step is not used, but simply after filtering, an unsafe stream type conversion is used, so the pipeline does not lengthen once again.nonNull()
method to replace filter(Objects::nonNull)
. There is also a remove(Predicate)
method that removes elements from the stream that satisfy the predicate ( filter
backwards). It allows more frequent use of references to methods: public List<String> readNonEmptyLines(Reader reader) { return StreamEx.ofLines(reader).map(String::trim).remove(String::isEmpty).toList(); }
findAny(Predicate)
and findFirst(Predicate)
- shortcuts for filter(Predicate).findAny()
and filter(Predicate).findFirst()
. The has
method allows you to find out if there is a specific element in the stream. Similar methods are added to primitive streams.Stream.concat
not very nice, as it adds nested brackets and spoils the idea of reading the program from left to right. To replace concat
I made append
and prepend
, which allow you to add another stream or a given set of values to the end or beginning of the current thread: public List<String> getDropDownOptions() { return StreamEx.of(users).map(User::getName).prepend("(none)").toList(); }
public int[] addValue(int[] arr, int value) { return IntStreamEx.of(arr).append(value).toArray(); }
Comparator.comparingInt
. To reduce the most common situations of sorting, searching for the maximum and minimum by one key, the family of methods sortingBy
, maxBy
and minBy
: public User getMostActiveUser() { return StreamEx.of(users).maxByLong(User::getNumberOfPosts).orElse(null); }
Stream
implement the Iterable
interface, because it contains an iterator()
method. This is not done, in particular, because Iterable
implies reusability, and the iterator can only be taken once from the stream. Although the Stack Overflow noted that the JDK already has an exception to this rule - DirectoryStream . Anyway, sometimes you want to use the usual for
loop instead of the terminal forEach
. This gives a number of advantages: you can use any variables, not only effectively final, you can throw any exceptions, it is easier to debug, shorter than the spectra, etc. In general, I think that there is no big sin if you created the stream and immediately use its in for
loop. Of course, care must be taken not to pass it on to methods that take Iterable
and can bypass it several times. Example: public void copyNonEmptyLines(Reader reader, Writer writer) throws IOException { for(String line : StreamEx.ofLines(reader).remove(String::isEmpty)) { writer.write(line); writer.write(System.lineSeparator()); } }
Map
keys whose values satisfy a given condition, or vice versa. To write this directly is somewhat sad: you have to mess with Map.Entry
. I hid it under the hood of the static methods ofKeys(map, valuePredicate)
and ofValues(map, keyPredicate)
: Map<String, Role> nameToRole; public Set<String> getEnabledRoleNames() { return StreamEx.ofKeys(nameToRole, Role::isEnabled).toSet(); }
Map
processing scenarios, a separate EntryStream
class has been EntryStream
- Map.Entry
object Map.Entry
. It partially repeats the functionality of StreamEx
, but also contains additional methods that allow processing keys and values separately. In some cases, this makes it easier to both generate a new Map
and disassemble an existing Map
. For example, you can invert Map-List like this (strings from lists of values fall into keys, and keys form new lists of values): public Map<String, List<String>> invert(Map<String, List<String>> map) { return EntryStream.of(map).flatMapValues(List::stream).invert().grouping(); }
flatMapValues
, which turns the stream Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Entry<String, List> Entry<String, String>
, invert
, , grouping
— Map
.
Map
:
public Map<String, String> stringMap(Map<Object, Object> map) { return EntryStream.of(map).mapKeys(String::valueOf).mapValues(String::valueOf).toMap(); }
, :
Map<String, Group> nameToGroup; public Map<String, List<User>> getGroupMembers(Collection<String> groupNames) { return StreamEx.of(groupNames).mapToEntry(nameToGroup::get).nonNullValues().mapValues(Group::getMembers).toMap(); }
mapToEntry
EntryStream
.
. , - . — GitHub , Maven Central . JavaDoc , . , , - .
Source: https://habr.com/ru/post/255659/
All Articles