java8--- groupingBy partitioningBy

 

 

 

    //多级分组
    //----------------------------------
    //MEAT
    //    FAT
    //        [Test.Dish(name=pork, vegetarain=false, colories=800, type=MEAT)]
    //    DIET
    //        [Test.Dish(name=chicken, vegetarain=false, colories=400, type=MEAT)]
    //    NORMAL
    //        [Test.Dish(name=beef, vegetarain=false, colories=700, type=MEAT)]
    //----------------------------------
    //FISH
    //    DIET
    //        [Test.Dish(name=prawns, vegetarain=false, colories=300, type=FISH)]
    //    The NORMAL
     //         [Test.Dish (name = Salmon, = vegetarain to false, colories = 450, type = FISH)]
     // ----------------------- -----------
     // OTHER
     //     the DIET
     //         [Test.Dish (name = Rice, vegetarain = to true, colories = 350, of the type = OTHER), Test.Dish (name = Fruit Season, = to true vegetarain, colories = 120, type = OTHER)]
     //     the NORMAL
     //         [Test.Dish (name = french Fries, to true vegetarain =, = 530. colories, type = OTHER), Test.Dish (name = Pizza, vegetarain to true =, colories = 550, type = OTHER)]
     // summary: core parameters groupingBy generator is K, V generator. V generator may be any type of collector Collector. 
    public  static  void group2 () {
        Map<Type, Map<CaloricLevel, List<Dish>>> byTypeAndCalory = dishes.stream().collect(
                groupingBy(Dish::getType,
                        groupingBy (D -> {
                                     / ** Write to note that if the time to take into account all cases * / 
                                    if (d.getColories () <= 400 ) {
                                         return CaloricLevel.DIET;
                                    } else if (d.getColories() <= 700) {
                                        return CaloricLevel.NORMAL;
                                    } else {
                                        return CaloricLevel.FAT;
                                    }
                                }
                        )
                )
        );
        byTypeAndCalory.forEach((type, byCalory) -> {
            System.out.println("----------------------------------");
            System.out.println(type);
            byCalory.forEach((level, dishList) -> {
                System.out.println("\t" + level);
                System.out.println("\t\t" + dishList);
            });
        });
    }

 

Summary: groupingBy core parameters for K generator, V generator. V generator may be any type of collector Collector.

For example, V number generator may be calculated to achieve a select count sql statement ( * ) from Group A by the Type Table

Map<Type, Long> typesCount = dishes.stream().collect(groupingBy(Dish::getType, counting()));
System.out.println(typesCount);
-----------
{FISH=2, MEAT=3, OTHER=4}

 

Find the highest score sql packet select MAX (id) from table A group by Type

Map<Type, Optional<Dish>> mostCaloricByType = dishes.stream()
        .collect(groupingBy(Dish::getType, maxBy(Comparator.comparingInt(Dish::getCalories))));

 

Optional here does not make sense, because certainly not null. Then I had to get out. Use collectingAndThen

Map<Type, Dish> mostCaloricByType = dishes.stream()
    .collect(groupingBy(Dish::getType,
        collectingAndThen(maxBy(Comparator.comparingInt(Dish::getCalories)), Optional::get)));

 

The results seem to come out here, but do not agree with IDEA, compiled yellow alarm, press prompted changes becomes:

Map<Type, Dish> mostCaloricByType = dishes.stream()
    .collect(toMap(Dish::getType, Function.identity(),
        BinaryOperator.maxBy(comparingInt(Dish::getCalories))));

Yes, groupingBy becomes toMap the, key or Type, value or Dish, but one more argument! ! Here responded pit at the beginning of the beginning of toMap presentation is easy to understand, it really will be with Gaosi. 
We know to a reorganization List Map will face the same problem k. When the same K, v is covered or whether it? Demo in front of the practice is that when there is k, k again inserted directly throw an exception: java.lang.IllegalStateException: Duplicate key Dish(name
=pork, vegetarian=false, calories=800, type=MEAT) at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) The correct approach is to provide a function of dealing with conflict, in this demo, the principle of dealing with conflict is to find the biggest, fits well with our group seeking maximum requirements. (Java8 really do not want to engage in learning function, and felt everywhere pit performance issues)

 

Continue sql database mapping, the packet summation select sum (score) from table a group by Type

Map<Type, Integer> totalCaloriesByType = dishes.stream()
    .collect(groupingBy(Dish::getType, summingInt(Dish::getCalories)));
However, other collectors and are often used in combination groupingBy mapping method is generated. This method takes two parameters: a function element made of a convection Transformation, other objects will transform collected. Its purpose is to accumulate before applying a mapping function for each input element, which would allow to receive a particular type of collector elements adapted to different types of objects. What I look at an actual example of this collector use. For example, you want to get, which CaloricLevel for each type of Dish, the menu has. GroupingBy we can combine the collector and mapping, as follows:

Map<Type, Set<CaloricLevel>> caloricLevelsByType = dishes.stream()
    .collect(groupingBy(Dish::getType, mapping(this::getCaloricLevel, toSet())));
ToSet used herein default HashSet, may be embodied manually specify toCollection (HashSet :: new new )

 

https://yq.aliyun.com/articles/610729?spm=a2c4e.11153940.0.0.6a255562myIiAj

 

Partition

 

Look at a more complex and more interesting example: the array is divided into prime and non-prime number.

First, the definition of a prime number partition function:


private boolean isPrime(int candidate) {
    int candidateRoot = (int) Math.sqrt((double) candidate);
    return IntStream.rangeClosed(2, candidateRoot).noneMatch(i -> candidate % i == 0);
}
Then find the prime and non-prime numbers from 1 to 100

Map<Boolean, List<Integer>> partitionPrimes = IntStream.rangeClosed(2, 100).boxed()
    .collect(partitioningBy(this::isPrime));

 

 

For example, if you are a vegetarian, you may want to separate menu in accordance with vegetarian and non-vegetarian:

Map<Boolean, List<Dish>> partitionedMenu = dishes.stream().collect(partitioningBy(Dish::isVegetarian));
Of course, the use of filter can achieve the same effect:

List<Dish> vegetarianDishes = dishes.stream().filter(Dish::isVegetarian).collect(Collectors.toList());
Partition, relatively speaking, the advantage is to save two copies, when you want to classify a list quite useless. At the same time, and as groupingBy, partitioningBy as there are overloads can specify the packet type value.

Map<Boolean, Map<Type, List<Dish>>> vegetarianDishesByType = dishes.stream()
    .collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
Map<Boolean, Integer> vegetarianDishesTotalCalories = dishes.stream()
    .collect(partitioningBy(Dish::isVegetarian, summingInt(Dish::getCalories)));
Map<Boolean, Dish> mostCaloricPartitionedByVegetarian = dishes.stream()
    .collect(partitioningBy(Dish::isVegetarian,
        collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));

 

 

 

 

 

 

 

 // use Skip () and the limit () paging 
    public  static  void Pages () {
         int the pageSize = 2 ;
         int the pageIndex = 2 ;
        List<Integer> expected = Lists.newArrayList(61, 62, 63, 64, 65, 66, 67, 68, 69, 70);
        List<Integer> result = Stream.iterate(1, i -> i + 1)
                .skip((pageIndex - 1) * pageSize)
                .limit(pageSize)
                .collect(toList());
        System.out.println(result);

//        assertEquals(expected, result);
    }

 

 

 

 

Foundation Classes

public  enum CaloricLevel {
        DIET, NORMAL, FAT
    }
    public enum Type {
        MEAT, FISH, OTHER,
    }
    static List<Dish> dishes;
    static {
        dishes = Lists.newArrayList(
                new Dish("pork", false, 800, Type.MEAT),
                new Dish("beef", false, 700, Type.MEAT),
                new Dish("chicken", false, 400, Type.MEAT),
                new Dish("french fries", true, 530, Type.OTHER),
                new Dish("rice", true, 350, Type.OTHER),
                new Dish("season fruit", true, 120, Type.OTHER),
                new Dish("pizza", true, 550, Type.OTHER),
                new Dish("prawns", false, 300, Type.FISH),
                new Dish("salmon", false, 450, Type.FISH)
        );
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    @ToString
    public  static  class Dish {
         Private String name; // / ** name * / 
        Private  boolean vegetarain; // / ** Are Vegetarian * / 
        Private  int colories; // / ** calories * / 
        Private Type of the type; // / * * type * / 
    }

Guess you like

Origin www.cnblogs.com/hahajava/p/12193317.html