Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appending to a list within a stream to a map

I'm attempting to consolidate multiple unnecessary web requests into a map, with the key connected to a location's ID, and the value being a list of products at that location.

The idea is to reduce the amount of requests to my flask server by creating a single request for each location, with a list of required products mapped to it.

I have tried to find others who has faced a similar problem using Java 8's streaming functionality, but I cannot find anyone who is trying to append to a list within a map.

Example;

public class Product {
    public Integer productNumber();
    public Integer locationNumber();
}

List<Product> products = ... (imagine many products in this list)

Map<Integer, List<Integer>> results = products.stream()
    .collect(Collectors.toMap(p -> p.locationNumber, p -> Arrays.asList(p.productNumber));

Also, the second p parameter cannot access the current product in stream.

Because of this, I have been unable to test if I can append to a List when the location number matches a pre-existing list. I don't believe I can use Arrays.asList(), as I believe its immutable.

At the end, the map should have many product numbers in a list per location. Is it possible to append Integers to a pre-existing list within a map?

like image 771
jeff2405 Avatar asked Apr 11 '19 04:04

jeff2405


People also ask

How do you add an object to a Stream?

To insert an element at the end of a stream, we need to change the order in which the arguments were passed to the Stream. concat() method. Now the resultant stream from the given element is passed as the second parameter to the Stream. concat() method.

Can we apply Stream on map?

Converting only the Value of the Map<Key, Value> into Stream: This can be done with the help of Map. values() method which returns a Set view of the values contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.

How to convert list to map using stream in Java 8?

In this post, we will see how to convert List to Map using Stream in java 8. Collectors’s toMap () can be used with stream to convert List to Map in java. Consider a class Named Movie which have 3 fields – id, name and genre Create a list of movies and convert with to map with name as key and genre as value.

How do you iterate through a list of streams?

Streams are useful to perform transformations on the elements, filter them or perform some reduction over them. To only iterate, use forEach, both on the list and in its map elements: maps.forEach (map -> map.forEach ( (key, value) -> /* use key and value here */));

What is the difference between a stream and a map?

2. Basic Idea The principal thing to notice is that Stream s are sequences of elements which can be easily obtained from a Collection. Maps have a different structure, with a mapping from keys to values, without sequence.

Can we convert a map structure to a stream structure?

However, this doesn't mean that we can't convert a Map structure into different sequences which then allow us to work in a natural way with the Stream API. Let's see ways of obtaining different Collection s from a Map, which we can then pivot into a Stream:


2 Answers

You may do it like so,

Map<Integer, List<Integer>> res = products.stream()
    .collect(Collectors.groupingBy(Product::locationNumber,
        Collectors.mapping(Product::productNumber, Collectors.toList())));
like image 55
Ravindra Ranwala Avatar answered Sep 28 '22 00:09

Ravindra Ranwala


The java collectors API is pretty powerful and have lots of nice utility method to solve this.


public class Learn {

    static class Product {
        final Integer productNumber;
        final Integer locationNumber;

        Product(Integer productNumber, Integer locationNumber) {
            this.productNumber = productNumber;
            this.locationNumber = locationNumber;
        }

        Integer getProductNumber() {
            return productNumber;
        }

        Integer getLocationNumber() {
            return locationNumber;
        }
    }

    public static Product of(int i, int j){
        return new Product(i,j);
    }

    public static void main(String[] args) {


        List productList = Arrays.asList(of(1,1),of(2,1),of(3,1),
                of(7,2),of(8,2),of(9,2));

        Map> results = productList.stream().collect(Collectors.groupingBy(Product::getLocationNumber,
                Collectors.collectingAndThen(Collectors.toList(), pl->pl.stream().map(Product::getProductNumber).collect(Collectors.toList()))));

        System.out.println(results);
    }
}

So, what we are doing here is we are streaming the product list and grouping the stream by the location attribute but with the twist that we want to transform the collected list of products to list of product numbers.

Collectors.collectingAndThen is precisely the method for this which will let you specify a main collector toList() and a transformer function which is nothing but again a stream to map product to product numbers. IN java API doc the main collector and transformer are labeled as downstream collector and finisher.

Please go through the Collectors source code to have a complete understanding as to how all these different collectors are defined.

like image 21
Swaraj Yadav Avatar answered Sep 27 '22 22:09

Swaraj Yadav