我正在编写一个自定义java 8收集器,它应该计算具有getValue()方法的POJO的平均值.这是代码:
public static Collector<BoltAggregationData, BigDecimal[], BigDecimal> avgCollector = new Collector<BoltAggregationData, BigDecimal[], BigDecimal>() {
@Override
public Supplier<BigDecimal[]> supplier() {
return () -> {
BigDecimal[] start = new BigDecimal[2];
start[0] = BigDecimal.ZERO;
start[1] = BigDecimal.ZERO;
return start;
};
}
@Override
public BiConsumer<BigDecimal[], BoltAggregationData> accumulator() {
return (a,b) -> {
a[0] = a[0].add(b.getValue());
a[1] = a[1].add(BigDecimal.ONE);
};
}
@Override
public BinaryOperator<BigDecimal[]> combiner() {
return (a,b) -> {
a[0] = a[0].add(b[0]);
a[1] = a[1].add(b[1]);
return a;
};
}
@Override
public Function<BigDecimal[], …Run Code Online (Sandbox Code Playgroud) 我想创建一个Map从List的PointS和有地图从里面用相同的parentId,如映射列表中的所有条目Map<Long, List<Point>>.
我用过Collectors.toMap()但不编译:
Map<Long, List<Point>> pointByParentId = chargePoints.stream()
.collect(Collectors.toMap(Point::getParentId, c -> c));
Run Code Online (Sandbox Code Playgroud) 如何先分组,然后使用Java流应用过滤?
示例:考虑此类Employee:我希望按部门分组,其中包含薪水大于2000的员工列表.
public class Employee {
private String department;
private Integer salary;
private String name;
//getter and setter
public Employee(String department, Integer salary, String name) {
this.department = department;
this.salary = salary;
this.name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我如何做到这一点
List<Employee> list = new ArrayList<>();
list.add(new Employee("A", 5000, "A1"));
list.add(new Employee("B", 1000, "B1"));
list.add(new Employee("C", 6000, "C1"));
list.add(new Employee("C", 7000, "C2"));
Map<String, List<Employee>> collect = list.stream()
.filter(e -> e.getSalary() > 2000)
.collect(Collectors.groupingBy(Employee::getDepartment));
Run Code Online (Sandbox Code Playgroud)
产量
{A=[Employee [department=A, salary=5000, name=A1]],
C=[Employee [department=C, …Run Code Online (Sandbox Code Playgroud) 我想初始化Map<String, BigDecimal>并希望始终BigDecimal从流外部添加相同的值.
BigDecimal samePrice;
Set<String> set;
set.stream().collect(Collectors.toMap(Function.identity(), samePrice));
Run Code Online (Sandbox Code Playgroud)
但是Java抱怨如下:
收集器类型中的Map(Function,Function)方法不适用于参数(Function,BigDecimal)
为什么我不能从外面使用BigDecimal?如果我写:
set.stream().collect(Collectors.toMap(Function.identity(), new BigDecimal()));
Run Code Online (Sandbox Code Playgroud)
它会起作用,但那当然不是我想要的.
我有一个从Google Places API中获取的Google PlaceSummary对象列表.我想通过他们的Google商家信息ID收集和分组,但也保留元素的顺序.我认为会起作用的是:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
places.stream()
.collect(Collectors.groupingBy(
PlaceSummary::getPlaceId,
LinkedHashMap::new,
Collectors.mapping(PlaceSummary::getPlaceId, toList())
));
Run Code Online (Sandbox Code Playgroud)
但它甚至不会编译.它看起来应该根据收集器上的Java API文档.
以前我有这个代码:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream()
.collect(Collectors.groupingBy(PlaceSummary::getPlaceId));
Run Code Online (Sandbox Code Playgroud)
但是.collect(),Streams API上的标准不保留后续元素的顺序HashMap(显然因为HashMaps是无序的).我希望输出为a,LinkedHashMap以便Map按每个桶的插入顺序排序.
但是,我建议的解决方案不能编译.首先,它不承认PlaceSummary::getPlaceId它,因为它说它不是一个功能 - 即使我知道它是.其次,它说我不能转换LinkedHashMap<Object, Object>成M. M应该是一个通用的集合,所以它应该被接受.
如何将List转换为LinkedHashMap使用Java Stream API?有简洁的方法吗?如果它太难理解我可能只是采用旧学前Java 8方法.
我注意到在将List转换为LinkedHashMap时还有另一个Stack Overflow答案,但是这没有我想要的解决方案,因为我需要收集'this'我正在迭代的对象.
我想把一个人的名单分组.一个人有一些属性,如姓名,国家,城镇,邮政编码等.我写了静态代码,非常有效:
Object groupedData = data.stream().collect(groupingBy(Person::getName, Collectors.groupingBy(Person::getCountry, Collectors.groupingBy(Person::getTown))));
Run Code Online (Sandbox Code Playgroud)
但问题是,这不是动态的.有时我想按名称和城镇分组,有时候按属性分组.我怎样才能做到这一点?非Java 8解决方案也是受欢迎的.
对于Collectors.groupingBy()那个返回Map<K,List<T>>,它暗示List<T>是为了评估流?
我没有看到列表排序的明确描述,而并发版本明确表示没有排序.如果它没有以某种方式订购,我会期望它是一个收藏品,我不会看到除了收到订单之外的其他订单.
我希望保证每个列表中的最后一个值是该组收到的最后一个值.
我想从地图地图转换内部地图.
旧地图:Map<String, Map<LocalDate, Integer>>整数表示秒
新地图: Map<String, Map<LocalDate, Duration>>
我试过创建了新的内部地图,但是出了错误
错误:java:找不到适合方法的
putAll(java.util.stream.Stream<java.lang.Object>)方法java.util.Map.putAll(java.util.Map<? extends java.time.LocalDate,? extends java.time.Duration>)不适用
oldMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> new HashMap<LocalDate, Duration>() {{
putAll(
e.getValue().entrySet().stream()
.map(x -> new HashMap.SimpleEntry<LocalDate, Duration>
(x.getKey(), Duration.ofSeconds(x.getValue())))
);
}}
));
Run Code Online (Sandbox Code Playgroud) 如何通过每个条目限制groupBy?
例如(基于此示例:stream groupBy):
studentClasses.add(new StudentClass("Kumar", 101, "Intro to Web"));
studentClasses.add(new StudentClass("White", 102, "Advanced Java"));
studentClasses.add(new StudentClass("Kumar", 101, "Intro to Cobol"));
studentClasses.add(new StudentClass("White", 101, "Intro to Web"));
studentClasses.add(new StudentClass("White", 102, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 106, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 103, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 104, "Advanced Web"));
studentClasses.add(new StudentClass("Sargent", 105, "Advanced Web"));
Run Code Online (Sandbox Code Playgroud)
此方法返回简单组:
Map<String, List<StudentClass>> groupByTeachers = studentClasses
.stream().collect(
Collectors.groupingBy(StudentClass::getTeacher));
Run Code Online (Sandbox Code Playgroud)
如果我想限制返回的集合怎么办?让我们假设我只想要每个老师的前N个课程.怎么做到呢?
我如何使用收集器将DAO列表转换为 Map<String, List<Pojo>>
daoList看起来像这样:
[0] : id = "34234", team = "gools", name = "bob", type = "old"
[1] : id = "23423", team = "fool" , name = "sam", type = "new"
[2] : id = "34342", team = "gools" , name = "dan", type = "new"
Run Code Online (Sandbox Code Playgroud)
我想对“团队”属性进行分组,并为每个团队提供一个列表,如下所示:
"gools":
["id": 34234, "name": "bob", "type": "old"],
["id": 34342, "name": "dan", "type": "new"]
"fool":
["id": 23423, "name": "sam", "type": "new"]
Run Code Online (Sandbox Code Playgroud)
Pojo看起来像这样:
@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class Pojo{
private String …Run Code Online (Sandbox Code Playgroud) collectors ×10
java ×10
java-8 ×10
java-stream ×9
grouping ×2
dictionary ×1
generics ×1
java-9 ×1