How to use group-1 result key1 in group-2 when use

2019-08-30 04:19发布

问题:

How to use group-1 result in group-2 by Java Lambda.

This question is update from my a solved problem: How to covert List to Map<T, <K, List<Person>>> use java lambda?

you can see the last code. the function key2 want to use function key1's result, how to do it?

class Person{
   int age;
   int cityCode;
   String name;
}

method:

// Map<age, Map<cityCode, List<Person>>>
public Map<Integer, Map<Integer, List<Person>>> covertListToMap(List<Person> list){

      // TODO: How to make List<Person> to Map<age, Map<cityCode, List<Person>>>

}



Function<Person, Integer> key1 = (Person p) -> {
            // do many sth then get a key1Result:
            int key1Result = p.getAge() * new Random(10).nextInt();
            return key1Result;
        };


Function<Person, Integer> key2 = (Person p) -> {
            //  Question: how to get and use Function key1 key1Result:

            int key1Result = 0;

            int result = p.getCityCode() + key1Result;
            return result;
        };

Map<Integer, Map<Integer, List<Person>>> collect = list.stream().collect(groupingBy(key1, groupingBy(key2)));

I write a wrong sample to show my meaning:

Map<Integer, Map<Integer, List<Person>>> collect = list.stream().collect(groupingBy((Person p) -> {
            int key1Result = p.getAge() * new Random(10).nextInt();
            return key1Result;  // perhaps, now, key1Result is 10
        }, groupingBy((Person p) -> {

            // now, I want to get the key1Result which is 10, How to do it?  
            int key1Result = 0;

            int result = p.getCityCode() + key1Result;
            return result;
        })));

回答1:

You can use the function apply(T t). According to the javadoc:

Applies this function to the given argument.

In your case, it would mean:

int key1Result = key1.apply(p)

Edit: As you modified your question, I add an answer, should be right if I understood what you wanted to do:

AtomicInteger atomicInteger = new AtomicInteger(0);
Map<Integer, Map<Integer, List<Person>>> collect = personList.stream().collect(Collectors
        .groupingBy(p -> {
                int age = p.getAge() * new Random(10).nextInt();
                atomicInteger.set(age);
                return age;
            }, Collectors.groupingBy(p2 -> p2.getCityCode() + atomicInteger.get())));

If you want to read more about AtomicInteger, see atomic. Basically it is a wrapper that will keep its variable between threads.



回答2:

1st you collect the required Map with your modified key

Map<Integer, Map<Integer, List<Person>>> collect2 = personList.stream().collect(Collectors
        .groupingBy(p -> p.getAge() * new Random(10).nextInt(),
                Collectors.groupingBy(Person::getCityCode)));

Then change the map. The problem in your this case is you are using nested Maps. And using the key of the outer Map you want to change the key of inner Map. So you there is not other way than to create a new inner Map for each outer Key.

Here I am iterating over each entry of outer map and creating a new proper (required) inner Map using the inner Map already present.

collect2.entrySet().stream().forEach(e -> {
    Integer key = e.getKey();
    Map<Integer, List<Person>> oldValueMap = e.getValue();
    Map<Integer, List<Person>> newValueMap = new HashMap<>();
    oldValueMap.keySet().forEach(k -> {
        newValueMap.put(k + key, oldValueMap.get(k));
    });
    e.setValue(newValueMap);
});


标签: java lambda