Reputation: 207
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
Upvotes: 6
Views: 2525
Reputation: 120848
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.
Upvotes: 7
Reputation: 298143
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);
Upvotes: 4
Reputation: 48258
maybe another option can be:
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);
Upvotes: 1
Reputation: 30819
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);
Upvotes: 3