Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java stream - get the result after splitting string twice

I have a String:

String modulesToUpdate = "potato:module1, tomato:module2";

I want to get from it only:

module1
module2

First I have to split it with "," and then with ":"

So, I did this:

String files[] = modulesToUpdate.split(",");

for(String file: files){
    String f[] = file.split(":");
    for(int i=0; i<f.length; i++){
        System.out.println(f[1])
    }
}

This works, but loop in the loop is not elegant.

I'm trying to do the same thing with streams.

So, I did this:

Stream.of(modulesToUpdate)
            .map(line -> line.split(","))
            .flatMap(Arrays::stream)
            .flatMap(Pattern.compile(":")::splitAsStream)
            .forEach(f-> System.out.println(f.toString().trim()));

Output:

potato
module1
tomato
module2

How to reduce/filter it to get only:

module1
module2
like image 567
nidis Avatar asked May 30 '17 12:05

nidis


4 Answers

Change a single line:

  .map(x -> x.split(":")[1])

instead of:

  .flatMap(Pattern.compile(":")::splitAsStream)

Or as @Holger mentions in the comment:

 .map(s -> s.substring(s.indexOf(':')+1))

this does not create the intermediate array at all.

That flatMap is returning a Stream and Streams don't have indexes, but you do need them in this case to get to the second token.

like image 135
Eugene Avatar answered Nov 17 '22 20:11

Eugene


The split operation can do all your steps at once.

Consider splitting with the separator pattern ,\s* instead of just , to get rid of the need for a subsequent trim operation. Likewise, we can treat the unwanted prefix (matching [^:]*?:) as part of the separator, to remove it.

There’s only one thing left; the first element has a prefix which is not treated as separator. We may do either, remove it manually before the stream operation

Pattern.compile(",\\s*[^:]*?:")
       .splitAsStream(modulesToUpdate.substring(modulesToUpdate.indexOf(':')+1))
       .forEach(System.out::println);

or we allow a prefix at the beginning of the string to be treated like a separator, which lets the split operation handle it, but creates an empty string at the beginning, which we have to skip

Pattern.compile("(^|,\\s*)[^:]*?:").splitAsStream(modulesToUpdate)
       .skip(1)
       .forEach(System.out::println);
like image 21
Holger Avatar answered Nov 17 '22 21:11

Holger


You can use skip inside flatMap, e.g.:

String modulesToUpdate = "potato:module1, tomato:module2";
Arrays.stream(modulesToUpdate.split(","))
.map(String::trim)
.flatMap(s -> Arrays.stream(s.split(":")).skip(1))
.forEach(System.out::println);
like image 3
Darshan Mehta Avatar answered Nov 17 '22 22:11

Darshan Mehta


maybe another option can be:

  1. split to multiple conditions
  2. Stream the array and collect the elements at odd positions

String modulesToUpdate = "potato:module1, tomato:module2";
String[] mod = modulesToUpdate.split("[:,]");
List<String> res = IntStream.range(0, mod.length)
                     .filter(j -> (j % 2) == 0)
                     .mapToObj(i -> mod[i])
                     .collect(Collectors.toList());
System.out.println(res);
like image 1
ΦXocę 웃 Пepeúpa ツ Avatar answered Nov 17 '22 20:11

ΦXocę 웃 Пepeúpa ツ