java - Code optimization to covert list of integers to list of objects in Java
问题描述
I have around 50000 to 500000 employee Ids and I want those employee ids to convert into detail objects.
I have done something like this to achieve that:
private Set<Detail> setDetail(List<Integer> employees, Group group) {
Set<Detail> details = employees.stream().parallel().map(id -> new Detail(id, group)).collect(Collectors.toSet());
return details ;
}
But this is very slow and getting more slower with increase number of employee ids. How I can optimize this code? What are the optimization techniques/algorithms I can use to better optimize this.
解决方案
您应该尽量避免创建那么多对象。无论您选择哪种算法,如果您的数据库在某个时候会继续增长,您将无法将其全部放入内存中。此外,瓶颈可能是从数据库获取数据(而不是创建对象)。
因此,请尝试重新构建您的应用程序,以便在执行相关操作时预先计算数据并将其存储在 DB 中。
如果经过仔细考虑,您决定确实需要使用这么多对象,那么更好的选择是继续使用原语:
class EmployeesInGroup {
private final int[] ids;
private final Group group;
...
Detail get(int idx) {
return new Details(ids[idx], group);
}
int size() {
return ids.length;
}
}
然后,您可以遍历此列表并一次使用 1 个对象,而无需在内存中保留大量对象:
EmployeesInGroup list = new EmployeesInGroup(ids, group);
for(int i = 0; i < list.size(); i++) {
Detail d = list.get(i);
...
}
您可以使其实现Iterable
并使用 for-each 循环。
基准
我上面列出的方法比创建Detail 对象数组至少快 20 倍。使用流和列表会更加缓慢。我没有检查,Integer
但我预测它会使一切速度减慢 2 或其他因素。
Benchmark Mode Cnt Score Error Units
EmployeeConversionBenchmark.objectArray thrpt 20 368.702 ± 3.483 ops/s
EmployeeConversionBenchmark.primitiveArray thrpt 20 7595.080 ± 68.841 ops/s
EmployeeConversionBenchmark.streamsWithObjects thrpt 20 197.923 ± 1.616 ops/s
这是我使用的代码:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static java.util.stream.Collectors.toList;
public class EmployeeConversionBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(new String[]{EmployeeConversionBenchmark.class.getSimpleName()});
}
@Benchmark @Fork(value = 1, warmups = 0)
public int primitiveArray(Data data) {
EmployeesInGroup e = new EmployeesInGroup(data.ids, data.group);
int sum = 0;
for (int i = 0; i < e.size(); i++)
sum += e.get(i).getId();
return sum;
}
@Benchmark @Fork(value = 1, warmups = 0)
public int objectArray(Data data) {
EmployeesInGroup.Detail[] e = new EmployeesInGroup.Detail[data.ids.length];
for (int i = 0; i < data.ids.length; i++)
e[i] = new EmployeesInGroup.Detail(data.ids[i], data.group);
int sum = 0;
for (EmployeesInGroup.Detail detail : e)
sum += detail.getId();
return sum;
}
@Benchmark @Fork(value = 1, warmups = 0)
public int streamsWithObjects(Data data) {
List<EmployeesInGroup.Detail> e = Arrays.stream(data.ids).mapToObj(id -> new EmployeesInGroup.Detail(id, data.group)).collect(toList());
int sum = 0;
for (EmployeesInGroup.Detail detail : e)
sum += detail.getId();
return sum;
}
@State(Scope.Benchmark)
public static class Data {
private final int[] ids = new int[500_000];
private final EmployeesInGroup.Group group = new EmployeesInGroup.Group();
public Data() {
for (int i = 0; i < ids.length; i++)
ids[i] = new Random().nextInt();
}
}
public static class EmployeesInGroup {
private final int[] ids;
private final Group group;
public EmployeesInGroup(int[] ids, Group group) {
this.ids = ids;
this.group = group;
}
public Detail get(int idx) {
return new Detail(ids[idx], group);
}
public int size() {
return ids.length;
}
public static class Group {
}
public static class Detail {
private final int id;
private final Group group;
public Detail(int id, Group group) {
this.id = id;
this.group = group;
}
public int getId() {
return id;
}
}
}
}
推荐阅读
- c++ - 数组无法在函数内正确播放 - 冒泡排序
- svn - 在没有多次提交目录属性的情况下忽略 svn repo 工作副本中某些文件的修改
- ios - 如何在 SwiftUI 中将 textField 键盘的“返回”按钮更改为蓝色的“完成”按钮?
- python-3.x - Python 3 - 在位置 p 的两个矩阵中对 2 个布尔值应用 AND 运算
- powershell - 如何使批处理文件在 vscode 终端中运行
- mongodb - 聚合MongoDB 3.4
- python - 使用 subprocess 模块获取输出并将输入发送到 minecraft 服务器
- android - setImageResource() 未通过 Firebase 获取图像
- c++ - 尝试使用 IPv6 连接两台计算机。(RakNet 和 C++)
- asp.net-core - 为非 api 项目创建 HealthCheck 以进行活性探测 openshift