Tony_Ynot
Tony_Ynot

Reputation: 155

How to compare 2 lists using Stream and get element form compare list?

//FullName(String name, String fullName)
List<FullName> fullNameList = Arrays.asList(
            new FullName("Alpha", "Alpha Maz"),
            new FullName("Beta", "Beta Sew"),
            new FullName("Delta", "Delta Non"),
            new FullName("Indigo", "Indigo Loe")
            );

List<String> nameList = Arrays.asList(new String[] {"Delta","Alpha"});

Lets take the example list above. I would like to compare nameList with fullNameList, and return the full name if any match found.

I have to use nameList as primary as I want the result to be following the sequence in nameList, I have no idea on how to "collect" the element from the compare list (fullNameList)

String result= nameList.stream()
            .filter(v -> fullNameList.stream().anyMatch(s -> s.getName().equals(v)))
            .collect(Collectors.joining(","));

Actual Result : "Delta,Alpha"
Expected Result : "Delta Non,Alpha Maz"

Any idea how to do it with Java 8 Stream ?

Upvotes: 1

Views: 209

Answers (4)

Priyak Dey
Priyak Dey

Reputation: 1367

Map<String, String> nameMapper = fullNameList.stream()
                    .collect(Collectors.toMap(FullName::getFirstName, FullName::getFullName));

List<String> filteredList = nameList.stream()
                            .filter(nameMapper::containsKey)
                            .map(nameMapper::get)
                            .collect(Collectors.toList());

System.out.println("nameList = " + nameList);
System.out.println("filteredList = " + filteredList);

nameList = [Indigo, Alpha, Delta] filteredList = [Indigo Loe, Alpha Maz, Delta Non]

nameList = [Delta, Alpha] filteredList = [Delta Non, Alpha Maz]

Though there is an overhead of creating a Map, in case of a realtime app, if the list is huge in number, then iteration cost will be less since fetching is O(1) since String in itself will less likely create hash collision. In the case of that too your fetching is O(log n).

In case of a smaller list, I think Eran's answer is more appropriate.

Upvotes: 1

Oleksii Zghurskyi
Oleksii Zghurskyi

Reputation: 4365

If you restricted to nameList as primary, then you can use the following:

String result = nameList.stream()
                .flatMap(name -> fullNameList.stream()
                        .filter(fullName -> fullName.getName().equals(name))
                        .map(FullName::getFullName)
                )
                .collect(Collectors.joining(","));

Upvotes: 0

Mak
Mak

Reputation: 1078

With a small change in your code, you can get your expected output.

String res = fullNameList.stream().filter(f -> nameList.stream().anyMatch(n -> n.equals(f.getName()))).map(f -> f.getfullName()).collect(Collectors.joining(",")); 

Output: Alpha Maz,Delta Non

Upvotes: 0

Eran
Eran

Reputation: 393801

You need to use map instead of filter in order to map a short name to the corresponding full name.

String result= 
    nameList.stream()
            .map(v -> fullNameList.stream()
                                  .filter(s -> s.getName().equals(v))
                                  .findFirst()
                                  .map(FullName::getFullName))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.joining(","));

This is assuming FullName class has a getFullName() method that returns the data you wish to collect.

Upvotes: 0

Related Questions