В чем разница между классификатором и последующим и только с использованием классификатора - PullRequest
0 голосов
/ 03 февраля 2019

Я новичок в Java 8 и собираю потоки, пытаясь понять, в чем заключается основное различие между ними?

Поскольку оба кода дают одинаковые результаты.Один использует return groupingBy(classifier, toList()); и возвращает groupingBy (классификатор, HashMap :: new, downstream);

Вот код

public class Grouping {
    enum CaloricLevel { DIET, NORMAL, FAT };

    public static void main(String[] args) {
        System.out.println("Dishes grouped by type: " + groupDishesByType());
        System.out.println("Dish names grouped by type: " + groupDishNamesByType());
    }


    private static Map<Type, List<Dish>> groupDishesByType() {
        return Dish.menu.stream().collect(groupingBy(Dish::getType));
    }

    private static Map<Type, List<String>> groupDishNamesByType() {
        return Dish.menu.stream().collect(groupingBy(Dish::getType, mapping(Dish::getName, toList())));
    }
}

вывод:

Dishes grouped by type: {MEAT=[pork, beef, chicken], OTHER=[french fries, rice, season fruit, pizza], FISH=[prawns, salmon]}
Dish names grouped by type: {MEAT=[pork, beef, chicken], OTHER=[french fries, rice, season fruit, pizza], FISH=[prawns, salmon]}

Dish.java

public class Dish {

    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {
        MEAT, FISH, OTHER
    }

    @Override
    public String toString() {
        return name;
    }

    public static final List<Dish> menu = asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT), 
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER), 
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER), 
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 400, Dish.Type.FISH), 
            new Dish("salmon", false, 450, Dish.Type.FISH));

    public static final Map<String, List<String>> dishTags = new HashMap<>();

    static {
        dishTags.put("pork", asList("greasy", "salty"));
        dishTags.put("beef", asList("salty", "roasted"));
        dishTags.put("chicken", asList("fried", "crisp"));
        dishTags.put("french fries", asList("greasy", "fried"));
        dishTags.put("rice", asList("light", "natural"));
        dishTags.put("season fruit", asList("fresh", "natural"));
        dishTags.put("pizza", asList("tasty", "salty"));
        dishTags.put("prawns", asList("tasty", "roasted"));
        dishTags.put("salmon", asList("delicious", "fresh"));
    }
}

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

в чем основная разница между этими двумя понятиями?

Основным отличием является отображение , которое вы сделали на промежуточном этапедо отделка коллектор.Хотя вы использовали их по-другому, хотя это подпись groupingBy.

В то время как с одной стороны , вы указали mapper и downstream вместе как:

.collect(Collectors.groupingBy(Dish::getType,  // classifier
             Collectors.mapping(Dish::getName,  // mapper <<<< difference here
                 Collectors.toList()))) // downstream

С другой стороны, реализация по умолчанию groupingBy используется в

.collect(Collectors.groupingBy(Dish::getType)) 

, которую можно расширить до некоторойформат похож на:

.collect(Collectors.groupingBy(Dish::getType, // classifier
             Collectors.mapping(Function.identity(),  // mapper
                 Collectors.toList()))); // downstream
0 голосов
/ 04 февраля 2019

В ваших двух примерах

.collect(groupingBy(Dish::getType));
.collect(groupingBy(Dish::getType, mapping(Dish::getName, toList())));

возвращаемое значение одинаково, потому что ваш toString() метод в Dish классе возвращает только name.Попробуйте добавить больше информации к toString() mehtod, и вы увидите разницу.

В общем, использование groupingBy только с классификатором позволяет группировать объекты, как в первом примере.Но использование goupingBy с классификатором и последующим потоком позволяет вам группировать гораздо больше, чем только ваши объекты.Например, вы можете сгруппировать средние калории по типу :

.collect(groupingBy(Dish::getType, averagingInt(Dish::getCalories));  // Map<Type, Double>

или найти наиболее калорийное блюдо каждого типа :

.collect(groupingBy(Dish::getType, maxBy(Comparator.comparingInt(Dish::getCalories)));  // Map<Type, Optional<Dish>>

ЧастоgroupingBy используется в качестве нисходящего потока для двойной группировки (по типу и по вегетарианству):

.collect(groupingBy(Dish::getType, groupingBy(Dish::isVegetarian)); // Map<Type, Map<Boolean, List<Dish>>>
0 голосов
/ 03 февраля 2019

Если это вопрос

Поскольку оба кода дают одинаковые результаты.Один использует return groupingBy (classifier, toList ());и вернуть groupingBy (классификатор, HashMap :: new, downstream);?

groupingBy (классификатор функций, коллектор нисходящий)

Нет никаких гарантий относительно типа, изменчивости, сериализуемости или безопасности потоковКарта вернулась.

groupingBy (Классификатор функций, Карта поставщика, Коллектор вниз по течению)

Карта, созданная Коллектором, создается с помощью предоставленногоЗаводская функция.

Разница лишь в том, что при использовании groupingBy с mapFactory созданное Map основано на логике вашего поставщика (может быть настраиваемой, неизменной, синхронизированной и т. д.)

...