6

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

4 Answers 4

7

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.

Sign up to request clarification or add additional context in comments.

1 Comment

or .map(s -> s.substring(s.indexOf(':')+1)), as it doesn’t create the array and irrelevant substrings in the first place.
4

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);

Comments

3

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);

Comments

1

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.