出于好奇,如果在java8风格中使用Comparator,即使用Lambda表达式比常规比较有任何优势,即
按ID排序的一种方法是: -
List sortedAcs = ac
.stream()
.sorted((a, b) -> Long.compare(a.getId(), b.getId())) //sorted by id here
.collect(Collectors.toList());
其他方法可能是Java 8方式: -
List sortedAcs = ac
.stream()
.sorted(Comparator.comparingLong(AC::getId)) //sorted by id here
.collect(Collectors.toList());
以后的方法(java-8 method reference
)与以前的方法相比,是否有任何性能优势?
请帮助!!!
答案 0 :(得分:7)
唯一不同的是完成你想要的方法所需的方法数量。 Comparator.comparingLong
会为每个参数应用ToLongFunction
,然后然后委托给Long.compare
。但这是一个JIT
应该处理的简单优化。我会说因为这个差异,可能会有一点点差异(直到JIT开始),但它会如此之小,以至于绝对可以忽略,不应该以任何方式推动你的决定。
另一方面,如果您确实发现任何差异,那么可能是您的测试代码是问题,而不是正在测量的代码。
答案 1 :(得分:2)
两个代码段中的任何性能差异都是可以忽略的。如果你真的需要优化代码,那么不使用流可能会比替换比较器提供更大的性能提升。
您应该使用两种变体进行选择的唯一标准是清晰度:您认为哪一个更清楚地传达了代码的意图?最后,这是个人偏好,取决于您对Java 8功能的流畅程度等等。
就个人而言,我发现第二个片段比第一个片段更清晰。 comparingLong
方法(以及其他comparingX
方法)立即告诉我:这里我们基于(long
- typed)属性的值来比较对象。在第一个片段中,我首先需要解析代码以确定确实发生了什么。
答案 2 :(得分:1)
所以,从一个角度来看答案,即表现。
以下是我用来测试它的代码: -
AC课程: -
package com.test;
public class AC {
private Long id;
public AC(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String toString() {
return "AC{" +
"id=" + id +
'}';
}
}
主要课程: -
package test.java;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
@org.openjdk.jmh.annotations.Benchmark
public void measureName() {
List<AC> acs = new ArrayList<>();
acs.add(new AC(20l));
acs.add(new AC(30l));
acs.add(new AC(10l));
acs.add(new AC(30l));
acs.add(new AC(80l));
acs.add(new AC(50l));
acs.add(new AC(30l));
acs.add(new AC(90l));
acs.add(new AC(80l));
acs.add(new AC(110l));
/* acs
.stream()
.sorted(Comparator.comparingLong(AC::getId)) //sorted by id here
.collect(Collectors.toList());*/
acs.stream()
.sorted((a, b) -> Long.compare(a.getId(), b.getId())) //sorted by id here
.collect(Collectors.toList());
}
public static void main(String[] args) {
Options opt = new OptionsBuilder()
.include(".*" + Main.class.getSimpleName() + ".*")
.forks(1)
.build();
try {
new Runner(opt).run();
} catch (RunnerException e) {
e.printStackTrace();
}
}
}
使用JMH将以下输出用于Comparator.comparingLong
: -
# Run complete. Total time: 00:00:40
Benchmark Mode Cnt Score Error Units
Main.measureName thrpt 20 4130836.283 ± 86675.431 ops/s
以及下面的Long.compare
: -
# Run complete. Total time: 00:00:40
Benchmark Mode Cnt Score Error Units
Main.measureName thrpt 20 4106542.318 ± 146956.814 ops/s
如果我按照这些统计数据Long.compare
以某种方式更快,但差异很小。
如果有的话,请随时发表评论,我也会尝试。
答案 3 :(得分:0)
我在收到有关
使用的警告之前,试图对地图进行排序(entry1,entry2)->Long.compare(entry1.getKey(),entry2.getKey())
应使用Comparator.comparingLong替换它,结果是实现它的更好方法:
Comparator.comparingLong(Map.Entry::getKey)
在对compareLong的实现进行检查时,我发现它基本上是相同的实现,只是它更干净且耗时更少。
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2))