0

Given 2 Maps and an object

Map<Integer, List<String>> fruits = new HashMap<>();
fruits.put(1, Arrays.asList("apple", "banana"));
fruits.put(2, Arrays.asList("orange", "kiwi"));

Map<Integer, List<String>> veggies= new HashMap<>();
veggies.put(1, Arrays.asList("tomato", "potato"));
veggies.put(2, Arrays.asList("onion"));

Class Food
{
    private id;
    private List<String> fruitsList;
    private List<String> veggiesList;

    //getters and setters
}

I am trying to combine the given 2 maps to a single list containing Food object(List).

//Used for explanation purpose
Food food1 = new Food();
food1.setId(1);
food1.setFruitsList(Arrays.asList("apple", "banana"));
food1.setVeggiesList(Arrays.asList("tomato", "potato"));

//Used for explanation purpose
Food food2 = new Food();
food2.setId(2);
food2.setFruitsList(Arrays.asList("orange", "kiwi"));
food2.setVeggiesList(Arrays.asList("onion"));

//Wanted this list of food
List<Food> foodList = new ArrayList();
foodList.add(food1);
foodList.add(food2);

I need to get a List. Can we achieve that using Java8 streams? Any solutions would be appreciated.

2 Answers 2

2

You can do something like this:

List<Food> foodList = fruits.keySet().stream()
    .concat(veggies.keySet().stream())
    .distinct()
    .map(id -> {
        Food food = new Food();
        food.setId(id);
        food.setFruitsList(fruits.getOrDefault(id, new ArrayList<>()));
        food.setVeggiesList(veggies.getOrDefault(id, new ArrayList<>()));
        return food ;
    })
    .collect(Collectors.toList());

If your Food class has a constructor taking the three parameters, it gets just a little more concise:

List<Food> foodList = fruits.keySet().stream()
    .concat(veggies.keySet().stream())
    .distinct()
    .map(id -> new Food(
        id,
        fruits.getOrDefault(id, new ArrayList<>()),
        veggies.getOrDefault(id, new ArrayList<>())
    )
    .collect(Collectors.toList());

If you know the ids are the same in both maps, you can skip the .concat() and .distinct() steps (which are quite expensive), and just use get() instead of getOrDefault().

You can also (in any case) do

Set<Integer> allKeys = new HashSet<>(fruits.keySet());
allKeys.addAll(veggies.keySet());
List<Food> foodList = allKeys.stream()
    .map(/* as before */)
    .collect(Collectors.toList());

which is not quite a "pure stream" a solution, but is probably more efficient.

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

Comments

1

You can merge the two keys streams and use a distinct method to get only unique keys.

List<Food> foods = Stream.concat(fruits.keySet().stream() , veggies.keySet().stream())
                         .distinct()
                         .map(e -> new Food(e, fruits.get(e), veggies.get(e)))
                         .collect(Collectors.toList());

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.