当前位置:  开发笔记 > 编程语言 > 正文

Java的性能可选

如何解决《Java的性能可选》经验,为你挑选了2个好方法。

我只是偶然发现了Java 8中的Optional类 - 我真的喜欢在我的代码中使用isPresent()方法调用替换一些空检查(字面意思是"值是否存在?")的方法.

我的问题是:这不会导致我的代码性能下降吗?我只是猜测简单的空检查可能会有点便宜而且我在字节码读取/解释方面还不是很好,所以我真的对你对这个主题的想法很感兴趣.



1> Javier Martí..:

Optional它只是一个普通的泛型类,它包含一个类型为T的引用.因此,它添加了一个单向的间接层.方法调用本身也不会非常昂贵,因为类是final,因此可以避免动态调度.

你可能遇到性能问题的唯一地方就是在处理大量此类实例时,但即便如此,像a这样的东西的表现也一点Stream>都不差.然而,随着大量的原始值的工作时,你会发现使用性能损失Stream(或Integer[])与原始专业化IntStream(或int[])由于这层间接的,需要的非常频繁实例化Integer对象.然而,这是我们已经知道并且在使用类似物时付出的代价ArrayList.

您显然会遇到与Stream/ 相同的命中OptionalInt[],因为OptionalInt基本上是一个带有int字段和存在boolean标志的类(与Optional仅使用T字段的情况不同)因此非常相似,Integer尽管尺寸更大.当然,a Stream>会增加两个间接级别,相应的双重性能损失.



2> Yuri Tcereti..:

我使用一种大量使用空检查的算法进行了一些性能测试,并访问了一个可能为空的字段.我实现了一个简单的算法,从单个链表中删除中间元素.

首先,我实现了两类链表节点:safe - with Optional和unsafe - without.

安全节点

class Node {
    private final T data;
    private Optional> next = Optional.empty();

    Node(T data) {

        this.data = data;
    }

    Optional> getNext() {
        return next;
    }

    void setNext(Node next) { setNext(Optional.ofNullable(next)); }

    void setNext(Optional> next ) { this.next = next; }
}

不安全的节点

class NodeUnsafe {
    private final T data;
    private NodeUnsafe next;

    NodeUnsafe(T data) {
        this.data = data;
    }

    NodeUnsafe getNext() {
        return next;
    }

    void setNext(NodeUnsafe next) {
        this.next = next;
    }
}

然后我实现了两个相似的方法,唯一的区别 - 第一次使用Node,第二次使用NodeUsafe 类DeleteMiddle {

class DeleteMiddle {
    private static  T getLinkedList(int size, Function supplier, BiConsumer reducer) {
        T head = supplier.apply(1);
        IntStream.rangeClosed(2, size).mapToObj(supplier::apply).reduce(head,(a,b)->{
            reducer.accept(a,b);
            return b;
        });
        return head;
    }

    private static void deleteMiddle(Node head){
        Optional> oneStep = Optional.of(head);
        Optional> doubleStep = oneStep;
        Optional> prevStep = Optional.empty();

        while (doubleStep.isPresent() && doubleStep.get().getNext().isPresent()){
            doubleStep = doubleStep.get().getNext().get().getNext();
            prevStep = oneStep;
            oneStep = oneStep.get().getNext();
        }

        final Optional> toDelete = oneStep;
        prevStep.ifPresent(s->s.setNext(toDelete.flatMap(Node::getNext)));
    }

    private static void deleteMiddleUnsafe(NodeUnsafe head){
        NodeUnsafe oneStep = head;
        NodeUnsafe doubleStep = oneStep;
        NodeUnsafe prevStep = null;

        while (doubleStep != null && doubleStep.getNext() != null){
            doubleStep = doubleStep.getNext().getNext();
            prevStep = oneStep;
            oneStep = oneStep.getNext();
        }
        if (prevStep != null) {
            prevStep.setNext(oneStep.getNext());
        }
    }

    public static void main(String[] args) {
        int size = 10000000;
        Node head = getLinkedList(size, Node::new, Node::setNext);
        Long before = System.currentTimeMillis();
        deleteMiddle(head);
        System.out.println("Safe: " +(System.currentTimeMillis() - before));

        NodeUnsafe headUnsafe = getLinkedList(size, NodeUnsafe::new, NodeUnsafe::setNext);
        before = System.currentTimeMillis();
        deleteMiddleUnsafe(headUnsafe);
        System.out.println("Unsafe: " +(System.currentTimeMillis() - before));
    }
}

使用不同大小的列表进行的两次运行的比较表明,使用Optional最佳代码的方法比使用nullables的代码慢两倍.使用小列表,它慢3倍.

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有