我是Java 8的新手,它收集了收集器,试图了解两者之间的基本区别是什么?
因为两个代码均获得相同的结果。一个使用return groupingBy(classifier, toList());
并返回groupingBy(classifier,HashMap :: new,下游);
这是代码
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"));
}
}
答案 0 :(得分:1)
如果这是问题
因为两个代码均获得相同的结果。一种使用return groupingBy(classifier,toList());并返回groupingBy(classifier,HashMap :: new,下游); ?
groupingBy(功能分类器,下游收集器)
无法保证返回的Map的类型,可变性,可序列化性或线程安全性。
groupingBy(功能分类器,供应商mapFactory, 下游收集器)
使用提供的工厂功能创建收集器生成的地图。
唯一的区别是,当您将$data = [
[
'id' => 1,
'parent_id' => '0',
'name' => 'A',
],
[
'id' => 2,
'parent_id' => '1',
'name' => 'A > B',
],
[
'id' => 3,
'parent_id' => '2',
'name' => 'A > B > C',
]
];
$names = array_column($data,'name','id');
print_r($names);
//[1 => 'A', 2 => 'A > B', 3 => 'A > B > C']
与groupingBy
一起使用时,mapFactory
的创建是基于您的供应商逻辑(可能是自定义的,不可变的,同步的等等)。
答案 1 :(得分:0)
两者之间的基本区别是什么?
主要区别是您在完成收集器之前的中间步骤中完成的 映射 。不过,您使用它们的不同方式是groupingBy
的签名。
一方面 ,但您将mapper
和downstream
统一指定为:
.collect(Collectors.groupingBy(Dish::getType, // classifier
Collectors.mapping(Dish::getName, // mapper <<<< difference here
Collectors.toList()))) // downstream
另一方面, deault implementation of groupingBy
用于
.collect(Collectors.groupingBy(Dish::getType))
可以扩展为类似于以下格式:
.collect(Collectors.groupingBy(Dish::getType, // classifier
Collectors.mapping(Function.identity(), // mapper
Collectors.toList()))); // downstream
答案 2 :(得分:0)
在您的两个示例中
.collect(groupingBy(Dish::getType));
.collect(groupingBy(Dish::getType, mapping(Dish::getName, toList())));
返回值相同,因为您的toString()
类中的Dish
方法仅返回name
。尝试将更多信息添加到toString()
方法中,您会发现有所不同。
通常,仅在分类器上使用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>>>