Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Lambda stream into different collections

Tags:

java

lambda

I have a Java lambda stream that parses a file and stores the results into a collection, based on some basic filtering.

I'm just learning lambdas so bear with me here if this is ridiculously bad. But please feel free to point out my mistakes.

For a given file:

#ignored
this
is
#ignored
working
fine

The code:

List<String> matches;

Stream<String> g = Files.lines(Paths.get(givenFile));

matches = g.filter(line -> !line.startsWith("#"))
           .collect(Collectors.toList());

["this", "is", "working", "fine"]

Now, how would I go about collecting the ignored lines into a second list within this same stream? Something like:

List<String> matches;
List<String> ignored; // to store lines that start with #

Stream<String> g = Files.lines(Paths.get(exclusionFile.toURI()));

matches = g.filter(line -> !line.startsWith("#"))
           // how can I add a condition to throw these
           // non-matching lines into the ignored collection?
           .collect(Collectors.toList());

I realize it would be pretty trivial to open a new stream, alter the logic a bit, and .collect() the ignored lines easily enough. But I don't want to have to loop through this file twice if I can do it all in one stream.

like image 433
AWT Avatar asked Oct 13 '16 03:10

AWT


People also ask

How Stream is different from collection in Java?

Differences between a Stream and a Collection: A stream does not store data. An operation on a stream does not modify its source, but simply produces a result. Collections have a finite size, but streams do not.

Which method can collect a Stream in a custom collection?

The toMap collector can be used to collect Stream elements into a Map instance.

What is the difference between the Stream API and the collections?

Difference Between Collections Vs Streams In Java :Collections are mainly used to store and group the data. Streams are mainly used to perform operations on data. You can add or remove elements from collections. You can't add or remove elements from streams.

How do I get a Stream from the collections?

You obtain a stream from a collection by calling the stream() method of the given collection. Here is an example of obtaining a stream from a collection: List<String> items = new ArrayList<String>(); items. add("one"); items.


1 Answers

Instead of two streams you can use partitioningBy in Collector

List<String> strings = Arrays.asList("#ignored", "this", "is", "#ignored", "working", "fine");
Map<Boolean, List<String>> map = strings.stream().collect(Collectors.partitioningBy(s -> s.startsWith("#")));
System.out.println(map);

output

{false=[this, is, working, fine], true=[#ignored, #ignored]}

here I used key as Boolean but you can change it to a meaningful string or enum

EDIT

If the strings can starts with some other special characters you could use groupingBy

    List<String> strings = Arrays.asList("#ignored", "this", "is", "#ignored", "working", "fine", "!Someother", "*star");
    Function<String, String> classifier = s -> {
        if (s.matches("^[!@#$%^&*]{1}.*")) {
            return Character.toString(s.charAt(0));
        } else {
            return "others";
        }
    };
    Map<String, List<String>> maps = strings.stream().collect(Collectors.groupingBy(classifier));
    System.out.println(maps);

Output

{!=[!Someother], #=[#ignored, #ignored], *=[*star], others=[this, is, working, fine]}

also you can nest groupingBy and partitioningBy

like image 170
Saravana Avatar answered Oct 01 '22 03:10

Saravana