inimene
inimene

Reputation: 1650

How to catch splitted string in java Stream

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

Answers (2)

Holger
Holger

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)

see Pattern.splitAsStream

Upvotes: 16

lbalazscs
lbalazscs

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

Related Questions