问题描述
我设法使用 Java 8 Streams API 编写了一个解决方案,该解决方案首先按值对对象 Route 列表进行分组,然后计算每个组中的对象数量.它返回一个映射 Route -> Long.代码如下:
I have managed to write a solution using Java 8 Streams API that first groups a list of object Route by its value and then counts the number of objects in each group. It returns a mapping Route -> Long. Here is the code:
Map<Route, Long> routesCounted = routes.stream()
.collect(Collectors.groupingBy(gr -> gr, Collectors.counting()));
还有路由类:
public class Route implements Comparable<Route> {
private long lastUpdated;
private Cell startCell;
private Cell endCell;
private int dropOffSize;
public Route(Cell startCell, Cell endCell, long lastUpdated) {
this.startCell = startCell;
this.endCell = endCell;
this.lastUpdated = lastUpdated;
}
public long getLastUpdated() {
return this.lastUpdated;
}
public void setLastUpdated(long lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Cell getStartCell() {
return startCell;
}
public void setStartCell(Cell startCell) {
this.startCell = startCell;
}
public Cell getEndCell() {
return endCell;
}
public void setEndCell(Cell endCell) {
this.endCell = endCell;
}
public int getDropOffSize() {
return this.dropOffSize;
}
public void setDropOffSize(int dropOffSize) {
this.dropOffSize = dropOffSize;
}
@Override
/**
* Compute hash code by using Apache Commons Lang HashCodeBuilder.
*/
public int hashCode() {
return new HashCodeBuilder(43, 59)
.append(this.startCell)
.append(this.endCell)
.toHashCode();
}
@Override
/**
* Compute equals by using Apache Commons Lang EqualsBuilder.
*/
public boolean equals(Object obj) {
if (!(obj instanceof Route))
return false;
if (obj == this)
return true;
Route route = (Route) obj;
return new EqualsBuilder()
.append(this.startCell, route.startCell)
.append(this.endCell, route.endCell)
.isEquals();
}
@Override
public int compareTo(Route route) {
if (this.dropOffSize < route.dropOffSize)
return -1;
else if (this.dropOffSize > route.dropOffSize)
return 1;
else {
// if contains drop off timestamps, order by last timestamp in drop off
// the highest timestamp has preceding
if (this.lastUpdated < route.lastUpdated)
return -1;
else if (this.lastUpdated > route.lastUpdated)
return 1;
else
return 0;
}
}
}
我想另外实现的是,每个组的键将是具有最大 lastUpdated 值的键.我已经在看这个解决方案,但我不知道如何将计数和分组按值和路由最大 lastUpdated 值结合起来.这是我想要实现的示例数据:
What I would like to additionally achieve is that the key for each group would be the one with the largest lastUpdated value. I was already looking at this solution but I do not know how to combine the counting and grouping by value and Route maximum lastUpdated value. Here is the example data of what I want to achieve:
示例:
List<Route> routes = new ArrayList<>();
routes.add(new Route(new Cell(1, 2), new Cell(2, 1), 1200L));
routes.add(new Route(new Cell(3, 2), new Cell(2, 5), 1800L));
routes.add(new Route(new Cell(1, 2), new Cell(2, 1), 1700L));
应该转换为:
Map<Route, Long> routesCounted = new HashMap<>();
routesCounted.put(new Route(new Cell(1, 2), new Cell(2, 1), 1700L), 2);
routesCounted.put(new Route(new Cell(3, 2), new Cell(2, 5), 1800L), 1);
注意映射的key,计算2条Routes的是lastUpdated值最大的那个.
Notice that the key for mapping, which counted 2 Routes is the one with the largest lastUpdated value.
推荐答案
这是一种方法.首先分组为列表,然后将列表处理为您实际想要的值:
Here's one approach. First group into lists and then process the lists into the values you actually want:
import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
Map<Route,Integer> routeCounts = routes.stream()
.collect(groupingBy(x -> x))
.values().stream()
.collect(toMap(
lst -> lst.stream().max(comparingLong(Route::getLastUpdated)).get(),
List::size
));
这篇关于按对象值分组,计数,然后按最大对象属性设置组键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!