首页 > 解决方案 > 提高/降低性能的 Cicles 方面

问题描述

我一直在对可变和不可变列表进行一些性能检查。我创建了以下测试。测试非常简单,我想知道我应该考虑哪些方面来改进 lambda 表达式以获得最接近或更好的 for 循环的性能。

到目前为止,我已经列出了其中一些:

  1. 排序列表将提高性能。
  2. 不可变集合也提高了性能。
  3. 使用 optional 会降低性能。

还有哪些方面会影响?

增强 - 经过时间:141

对于 - 经过时间:109

迭代器 - 经过时间:125

流 - 经过时间:172

并行流 - 经过时间:94

可选流 - 经过时间:156

可选并行流 - 经过时间:140

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

class MyObject {
    private Integer id;
    private String name;
    private String message;
    private MySecondObject object;
    public MyObject(Integer id, String name, String message, MySecondObject object) {
        this.id = id;
        this.name = name;
        this.message = message;
        this.object = object;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public MySecondObject getObject() {
        return object;
    }
    public void setObject(MySecondObject object) {
        this.object = object;
    }
    @Override
    public int hashCode() {
        int hash = 8;
        hash = 14 * hash + Objects.hashCode(this.id);
        hash = 14 * hash + Objects.hashCode(this.name);
        hash = 14 * hash + Objects.hashCode(this.message);
        hash = 14 * hash + Objects.hashCode(this.object);
        return hash;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MyObject other = (MyObject) obj;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.message, other.message)) {
            return false;
        }
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        return Objects.equals(this.object, other.object);
    }
    @Override
    public String toString() {
        return "\nMyObject{" + "id=" + id + ", name=" + name + ", message=" + message + ", object=" + object + '}';
    }
}

class MySecondObject {
    private Integer id;
    private String name;
    private String message;
    public MySecondObject(Integer id, String name, String message) {
        this.id = id;
        this.name = name;
        this.message = message;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 13 * hash + Objects.hashCode(this.id);
        hash = 13 * hash + Objects.hashCode(this.name);
        hash = 13 * hash + Objects.hashCode(this.message);
        return hash;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MySecondObject other = (MySecondObject) obj;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.message, other.message)) {
            return false;
        }
        return Objects.equals(this.id, other.id);
    }
    @Override
    public String toString() {
        return "MySecondObject{" + "id=" + id + ", name=" + name + ", message=" + message + '}';
    }
}

class MyObjectUtil {
    private MyObjectUtil() {
    }
    public static List<?> getList() {
        List<MyObject> myObjectList = new ArrayList<>();
        final ThreadLocalRandom r = ThreadLocalRandom.current();
        for (int i = 0; i < 1_000_000; i++) {
            myObjectList.add(new MyObject(r.nextInt(), "Name " + i, "Message " + i, new MySecondObject(r.nextInt(), "Second Object " + i, "Message " + i)));
        }
        myObjectList.add(new MyObject(r.nextInt(), "Name " + 0, "Message " + 0, null));
        myObjectList.sort((a, b) -> a.getId().equals(b.getId()) ? 0 : a.getId()> b.getId()? 1 : -1);
        return Collections.unmodifiableList(myObjectList);
        //return myObjectList;
    }
}

public class MyObjectListTest {

    public static void main(String[] args) {
        List<MyObject> myObjectList = (List<MyObject>) MyObjectUtil.getList();

        long begin = System.currentTimeMillis();
        List<Integer> idList = new ArrayList<>();
        if (myObjectList != null) {
            for (MyObject object : myObjectList) {
                if (object != null && object.getObject() != null) {
                    idList.add(object.getObject().getId());
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("\nEnhanced For - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        idList = new ArrayList<>();
        if (myObjectList != null) {
            for (int i = 0; i < myObjectList.size(); i++) {
                MyObject o = myObjectList.get(i);
                if (o != null && o.getObject() != null) {
                    idList.add(o.getObject().getId());
                }
            }
        }
        end = System.currentTimeMillis();
        System.out.println("\nFor - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        idList = new ArrayList<>();
        if (myObjectList != null) {
            for (Iterator<MyObject> it = myObjectList.iterator(); it.hasNext();) {
                MyObject m = it.next();
                if (m.getObject() != null) {
                    idList.add(m.getObject().getId());
                }
            }
        }
        end = System.currentTimeMillis();
        System.out.println("\nIterator - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        if (myObjectList != null) {
            idList = myObjectList
                    .stream()
                    .map(MyObject::getObject)
                    .filter(Objects::nonNull)
                    .map(MySecondObject::getId)
                    .collect(Collectors.toList());
        }
        end = System.currentTimeMillis();
        System.out.println("\nStream - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        if (myObjectList != null) {
            idList = myObjectList
                    .parallelStream()
                    .map(MyObject::getObject)
                    .filter(Objects::nonNull)
                    .map(MySecondObject::getId)
                    .collect(Collectors.toList());
        }
        end = System.currentTimeMillis();
        System.out.println("\nParallel Stream - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        idList = Optional.ofNullable(myObjectList)
                .orElseGet(Collections::emptyList)
                .stream()
                .map(MyObject::getObject)
                .filter(Objects::nonNull)
                .map(MySecondObject::getId)
                .collect(Collectors.toList());
        end = System.currentTimeMillis();
        System.out.println("\nOptional Stream - Elapsed time: " + (end - begin));

        idList = null;
        begin = System.currentTimeMillis();
        idList = Optional.ofNullable(myObjectList)
                .orElseGet(Collections::emptyList)
                .parallelStream()
                .map(MyObject::getObject)
                .filter(Objects::nonNull)
                .map(MySecondObject::getId)
                .collect(Collectors.toList());
        end = System.currentTimeMillis();
        System.out.println("\nOptional Parallel Stream - Elapsed time: " + (end - begin));
    }
}

谢谢。

标签: javaperformanceloopsfunctional-programmingstructured-programming

解决方案


推荐阅读