How to filter a List using Java 8 stream and startwith array of values
Asked Answered
L

4

6

I have 2 Lists, the one contains a list of numbers and the other a list of names. I have prefixed the names with a number from the first list, followed by an underscore. I want to filter the second list based on all the numbers found in the first list.

What I have tried.

List<String> numberList = new ArrayList<>();
numberList.add("1_");
numberList.add("9_");

List<String> nameList = new ArrayList<>();
nameList.add("1_John");
nameList.add("2_Peter");
nameList.add("9_Susan");

List<String> filteredList = Stream.of(numberList.toArray(new String[0]))
                .filter(str -> nameList.stream().anyMatch(str::startsWith))
                .collect(Collectors.toList());

The code above runs with no error, but the filteredList is empty. Clearly I am doing something wrong.

The filteredList should contain only:

1_John

9_Susan

Laevogyrate answered 28/5, 2019 at 6:32 Comment(1)
To create a stream from a Collection just use the existing API as Stream.of(numberList.toArray(new String[0])) => numberList.stream(). While you're actually iterating on the incorrect list using the streams. It should be the second list to iterate on and first used to filter in.Azine
A
5

You call startsWith on the wrong Strings (for example, you test if "1_".startsWith("1_John") instead of "1_John".startsWith("1_")).

You should stream over nameList and use numberList for the filtering:

List<String> filteredList = 
    nameList.stream()
            .filter(str -> numberList.stream().anyMatch(str::startsWith))
            .collect(Collectors.toList());

P.S. Stream.of(numberList.toArray(new String[0])) is redundant. Use numberList.stream() instead.

Airman answered 28/5, 2019 at 6:35 Comment(0)
A
4

As an alternate to Eran's solution, you can also use a combination of removeIf and noneMatch as follows:

List<String> filteredList = new ArrayList<>(nameList);
filteredList.removeIf(str -> numberList.stream().noneMatch(str::startsWith));
Azine answered 28/5, 2019 at 6:42 Comment(1)
Thanks, I will also give this a try to see it in action.Laevogyrate
C
0

Another attempt to give a solution could be to use contains , though the actual implementation of startsWith and contains are different but in OP case both will fetch the same result.

List<String> strList = nameList.stream().filter(s->numberList.stream().anyMatch(s::contains)).collect(Collectors.toList());

Output:

[1_John, 9_Susan]

Cathern answered 28/5, 2019 at 10:29 Comment(0)
L
0
List<String> numberList = new ArrayList<>();
numberList.add("1_");
numberList.add("9_");

List<String> nameList = new ArrayList<>();
nameList.add("1_John");
nameList.add("2_Peter");
nameList.add("9_Susan");

Following is the correct code:

enter image description here

Your code uses the following:

enter image description here

Lambard answered 29/5, 2019 at 9:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.