Reputation: 601
I have a string like this "-FOREST&-JUNGLE&DESERT"
This string is split up into words in a list like so: [-FOREST, -JUNGLE ,DESERT]
List<String> pattern = Arrays.asList(s.split("\\s*&\\s*"));
Every word with a minus at the beginning must be in one new list and every word without in another like so:
List<String> allowedtags = pattern
.stream()
.filter(name -> !name.startsWith("-"))
.collect(Collectors.toList());
List<String> unwantedtags = pattern
.stream()
.filter(name -> name.startsWith("-"))
.collect(Collectors.toList());
My problem is that my unwantedtags
keeps words with a minus at the beginning, but for all my operations I need to get rid of it. If I do the example below, it will not work if "FOREST" is in taglist
as my unwantedtags
contains "-FOREST".
if (taglist.stream().anyMatch(unwantedtags::contains)) {
return !IsWhitelist;
}
So how can I fix my unwantedtags list? Maybe in java 8 stream api? Moreover I have the feeling that on the one hand it is working fine to that point, but on the other hand I get the feeling that this is a lot of code for getting just two lists. Can it be optimized?
Upvotes: 1
Views: 1511
Reputation: 4140
You can use groupingBy
to divide this collection (by name.startsWith("-")
):
Map<Boolean, List<String>> collect = pattern.stream()
.collect(Collectors.groupingBy(name -> name.startsWith("-")));
Then you have:
{false=[DESERT], true=[-FOREST, -JUNGLE]}
After that you can do further processing (with unwantedtags
):
List<String> unwantedtags = collect
.getOrDefault(true, List.of()).stream()
.map(name -> name.substring(1))
.collect(Collectors.toList());
Or you can do it in one stream but it can look more complicated.
Map<Boolean, List<String>> collectWithMap = pattern.stream()
.collect(Collectors.groupingBy(name -> name.startsWith("-"),
Collectors.mapping(name -> name.startsWith("-") ? name.substring(1) : name,
Collectors.toList())));
result:
{false=[DESERT], true=[FOREST, JUNGLE]}
Upvotes: 0
Reputation: 234847
You can map each element to strip out the leading minus sign after it has been detected:
List<String> unwantedtags = pattern
.stream()
.filter(name -> name.startsWith("-"))
.map(name -> name.substring(1))
.collect(Collectors.toList());
The code can be made more efficient by constructing and populating the lists explicitly. Then you can process pattern
in a single pass instead of two:
List<String> allowedtags = new ArrayList();
List<String> unwantedtags = new ArrayList();
pattern.stream()
.forEach(name -> {
if (name.startsWith("-")) unwantedtags.add(name.substring(1));
else allowedtags.add(name);
}
);
Upvotes: 3
Reputation: 61
You are missing a single Operation. With the map() Operator you can take the input string and modify it.
List<String> unwantedtags = pattern
.stream()
.filter(name -> name.startsWith("-"))
.map(name -> name.substring(1))
.collect(Collectors.toList());
Upvotes: 2