user3684675
user3684675

Reputation: 381

creating Map from List is not giving expected result

I have the two list objects as shown below, from which i'm creating the map object.

List<Class1> list1;
List<Class2> list2;
HashMap<String,String> map = new HashMap<>();
for(Class1 one : list1){
 if(one.isStatus()){
   map.put(one.getID(),one.getName());
}
}

//iterating second list
for(Class2 two : list2){
 if(two.isPerformed()){
  map.put(two.getID(),two.getName());
}
}

The above code works fine , want the above to be written using streams. Below is the sample code using streams().

 map = list1.stream().filter(one.isStatus()).collect(toMap(lst1 -> lst1.getID(), lst1.getName());
 map = list2.stream().filter(...);

But the "map" is not giving the expected result when written using stream() API.

Upvotes: 1

Views: 194

Answers (3)

Nowhere Man
Nowhere Man

Reputation: 19545

Stream concatenation Stream.concat may be applied here to avoid map.putAll

Map<String, String> map = Stream.concat(
    list1.stream()
         .filter(Class1::isStatus)
         .map(obj -> Arrays.asList(obj.getID(), obj.getName())),
    list2.stream()
         .filter(Class2::isPerformed)
         .map(obj -> Arrays.asList(obj.getID(), obj.getName()))
) // Stream<List<String>>
.collect(Collectors.toMap(
    arr -> arr.get(0), // key - ID
    arr -> arr.get(1),
    (v1, v2) -> v1     // keep the first value in case of possible conflicts
));

The code above uses a merge function (v1, v2) -> v1 to handle possible conflicts when the same ID occurs several times in list1 and/or list2 to keep the first occurrence.

However, the following merge function allows joining all the occurrences into one string value (v1, v2) -> String.join(", ", v1, v2).

Upvotes: 1

ray
ray

Reputation: 1670

Try this,

List<Class1> list1;
List<Class2> list2;

Map<String, String> map1 = list1.stream().filter(Class1::isStatus).collect(Collectors.toMap(Class1::getId, Class1::getName));
Map<String, String> map2 = list2.stream().filter(Class2::isPerformed).collect(Collectors.toMap(Class2::getId, Class2::getName));

map1.putAll(map2);

Upvotes: 1

Sam Orozco
Sam Orozco

Reputation: 1258

I'm not sure what expected result you're not seeing but I created a minimal working example that you should be able to adapt for your own use case.

public class Main {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();

        Map<Integer, String> personMap = personList.stream()
                                                   .filter(Person::isStatus)
                                                   .collect(Collectors.toMap(person -> person.id, person -> person.name));
    }

    private static class Person {
        public String name;
        public int id;


        public boolean isStatus() {
            return true;
        }
    }
}

Upvotes: 1

Related Questions