Reputation: 1650
So let's say that we have a string: "randomText1 randomText2" in an array, which is loaded into a Stream.
Now I go over all the lines in this stream, and I split every line at the space character.
strings
.map(string -> string.split(" "))
.flatMap(Arrays::stream)
.collect(new MyClass(string1, string2));
How can I get the both sides of the string and do whatever I want with them from there on?
From Oracle docs (Oracle doc link) I only managed to find some harder cases where one would be using a Map<>
for instance. But I fail to fit their solutions to this more simpler problem of mine.
Upvotes: 6
Views: 22316
Reputation: 298143
Using flatMap
is not the right tool for the job. What you apparently want to do is
strings.map(string -> string.split(" ", 2))
.map(array -> new MyClass(array[0], array[1]))
You may process the stream further by using .collect(Collectors.toList())
to get a List<MyClass>
or .findAny()
to get a single MyClass
instance (if any).
Generally, streaming an array is only useful if you want to treat all elements uniformly, i.e. not if their position has a special meaning which has to be preserved for subsequent operations.
And if you really want to create a flat stream of words or tokens, you shouldn’t use the combination of String.split
and Arrays.stream
as that will create and fill an unnecessary intermediate array. In this case use
strings.flatMap(Pattern.compile(" ")::splitAsStream)
Upvotes: 16
Reputation: 17784
It was an interesting challenge even if streams should not be used for such simple tasks. Here's the complete code:
public class Example {
public static void main(String[] args) {
String[] strings = {"randomText1 randomText2"};
MyClass myClass = Arrays.stream(strings)
.map(string -> string.split(" "))
.flatMap(Arrays::stream)
.collect(new MyCollector());
System.out.println("myClass = " + myClass.toString());
}
}
class MyCollector implements Collector<String, List<String>, MyClass> {
@Override
public BiConsumer<List<String>, String> accumulator() {
return List::add;
}
@Override
public Supplier<List<String>> supplier() {
return ArrayList::new;
}
@Override
public BinaryOperator<List<String>> combiner() {
return (strings, strings2) -> {
strings.addAll(strings2);
return strings;
};
}
@Override
public Function<List<String>, MyClass> finisher() {
return strings -> new MyClass(strings.get(0), strings.get(1));
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
class MyClass {
String s1;
String s2;
public MyClass(String s1, String s2) {
this.s1 = s1;
this.s2 = s2;
}
@Override
public String toString() {
return "MyClass{" +
"s1='" + s1 + '\'' +
", s2='" + s2 + '\'' +
'}';
}
}
Upvotes: 3