获取与 POJO 变量的最大值匹配的所有 POJO 项
Getting all the POJO items that match max value of a POJO variable
我有一个 POJO class,我想从中收集与给定 POJO 变量的最大值相匹配的所有 POJO 对象。
我有下面的 POJO class
@Data
@AllArgsConstructor
@NoArgsConstructor
public class IPTraceData implements Serializable {
private String factId;
private long startIp;
private long endIp;
private int confidence;
private LocalDate date;
private long ipaddr;
}
我想获取所有与 confidence 变量的最大值相匹配的 POJO 对象。
我可以在 Java 8.
中使用以下代码获得结果
int max = allTraces.stream()
.max(Comparator.comparing(IPTraceData::getConfidence))
.get()
.getConfidence();
List<IPTraceData> traceData = allTraces
.stream()
.filter(m -> m.getConfidence() == max)
.collect(Collectors.toList());
但是,我正在尝试使用单个流语句在 Java8 中编写代码。
如何使用单流语句实现相同的目的?
从技术上讲,可以使用 单个语句 来实现该逻辑。但是这个解决方案有一个额外的成本,即在内存中分配一个中间映射 Map<Integer,<List<IPTraceData>>
.
先找到max confidence然后再根据它处理数据集的做法比较performance-wise.
List<IPTraceData> traceData = allTraces
.stream()
.collect(Collectors.groupingBy(IPTraceData::getConfidence))
.entrySet().stream()
.max(Map.Entry.comparingByKey())
.map(Map.Entry::getValue)
.orElse(Collections.emptyList());
注:
- 当代码不包含任何确保可选对象不为空的检查时,避免将
get()
与可选对象一起使用。如果您希望它不为空并且您的意图是使代码无法强调问题,请改用 orElseThrow()
。这会让你的意图更加明确。
如果你想在不使用额外的中间内存的情况下完成它,并且完全可并行化,你可以使用通用的 collect
功能。像这样的东西(未经测试;随意提取方法以使其更具可读性):
List<IPTraceData> traceData = allTraces.stream()
.collect(
// supplier
ArrayList::new,
// accumulator
(r, t) -> {
if (r.isEmpty()) {
r.add(t);
} else {
int currentMaxConfidence = r.get(0).getConfidence();
if (t.getConfidence() == currentMaxConfidence) {
r.add(t);
} else if (t.getConfidence() > currentMaxConfidence) {
r.clear();
r.add(t);
}
}
},
// combiner
(left, right) -> {
if (left.isEmpty()) {
left.addAll(right);
} else if (!right.isEmpty()) {
int leftMax = left.get(0).getConfidence();
int rightMax = right.get(0).getConfidence();
if (leftMax == rightMax) {
left.addAll(right);
} else if (leftMax < rightMax) {
left.clear();
left.addAll(right);
}
}
}
);
您也可以使用 reduce()
而不是 collect()
对 non-mutable 数据结构做同样的事情,但是使用普通的 Java 列表有点麻烦non-mutable 方式。
请注意,我知道该代码非常笨拙,可能不值得,但我纯粹是在回答您的问题,对您要如何使用它以及在何处使用它没有任何假设。
我有一个 POJO class,我想从中收集与给定 POJO 变量的最大值相匹配的所有 POJO 对象。
我有下面的 POJO class
@Data
@AllArgsConstructor
@NoArgsConstructor
public class IPTraceData implements Serializable {
private String factId;
private long startIp;
private long endIp;
private int confidence;
private LocalDate date;
private long ipaddr;
}
我想获取所有与 confidence 变量的最大值相匹配的 POJO 对象。
我可以在 Java 8.
中使用以下代码获得结果int max = allTraces.stream()
.max(Comparator.comparing(IPTraceData::getConfidence))
.get()
.getConfidence();
List<IPTraceData> traceData = allTraces
.stream()
.filter(m -> m.getConfidence() == max)
.collect(Collectors.toList());
但是,我正在尝试使用单个流语句在 Java8 中编写代码。 如何使用单流语句实现相同的目的?
从技术上讲,可以使用 单个语句 来实现该逻辑。但是这个解决方案有一个额外的成本,即在内存中分配一个中间映射 Map<Integer,<List<IPTraceData>>
.
先找到max confidence然后再根据它处理数据集的做法比较performance-wise.
List<IPTraceData> traceData = allTraces
.stream()
.collect(Collectors.groupingBy(IPTraceData::getConfidence))
.entrySet().stream()
.max(Map.Entry.comparingByKey())
.map(Map.Entry::getValue)
.orElse(Collections.emptyList());
注:
- 当代码不包含任何确保可选对象不为空的检查时,避免将
get()
与可选对象一起使用。如果您希望它不为空并且您的意图是使代码无法强调问题,请改用orElseThrow()
。这会让你的意图更加明确。
如果你想在不使用额外的中间内存的情况下完成它,并且完全可并行化,你可以使用通用的 collect
功能。像这样的东西(未经测试;随意提取方法以使其更具可读性):
List<IPTraceData> traceData = allTraces.stream()
.collect(
// supplier
ArrayList::new,
// accumulator
(r, t) -> {
if (r.isEmpty()) {
r.add(t);
} else {
int currentMaxConfidence = r.get(0).getConfidence();
if (t.getConfidence() == currentMaxConfidence) {
r.add(t);
} else if (t.getConfidence() > currentMaxConfidence) {
r.clear();
r.add(t);
}
}
},
// combiner
(left, right) -> {
if (left.isEmpty()) {
left.addAll(right);
} else if (!right.isEmpty()) {
int leftMax = left.get(0).getConfidence();
int rightMax = right.get(0).getConfidence();
if (leftMax == rightMax) {
left.addAll(right);
} else if (leftMax < rightMax) {
left.clear();
left.addAll(right);
}
}
}
);
您也可以使用 reduce()
而不是 collect()
对 non-mutable 数据结构做同样的事情,但是使用普通的 Java 列表有点麻烦non-mutable 方式。
请注意,我知道该代码非常笨拙,可能不值得,但我纯粹是在回答您的问题,对您要如何使用它以及在何处使用它没有任何假设。