首页 > 解决方案 > 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.

标签: javaoptimization

解决方案


您应该尽量避免创建那么多对象。无论您选择哪种算法,如果您的数据库在某个时候会继续增长,您将无法将其全部放入内存中。此外,瓶颈可能是从数据库获取数据(而不是创建对象)。

因此,请尝试重新构建您的应用程序,以便在执行相关操作时预先计算数据并将其存储在 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;
            }
        }
    }
}

推荐阅读