首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java List Horrible添加性能

Java List Horrible添加性能
EN

Stack Overflow用户
提问于 2017-01-01 04:05:17
回答 0查看 511关注 0票数 5

我正在向List中添加数百万个自定义对象的条目。这被证明是非常慢的,而且图形用户界面也会随机冻结(在Windows上不响应),即使添加操作被包装在SwingWorker中,所以它应该不会影响EDT。此外,CPU利用率上升到70% - 90%左右。

我将列表初始化为:

代码语言:javascript
运行
复制
List<SearchResult> updatedSearchResults = new ArrayList<>();

然后我不断地打电话给

代码语言:javascript
运行
复制
SearchResult searchResult = new SearchResult(...);
updatedSearchResults.add(searchResult);

添加元素。

我知道ArrayList内部使用了一个数组,该数组在满时会调整大小,并且所有元素都会被复制过来。但是,使用LinkedList比使用ArrayList要慢,而且不存在其他List实现。

根据this answer的说法,添加到ArrayList具有O(1)的性能。问题来了,为什么我收集所有结果的方法在性能方面仍然如此糟糕。SearchResult是一个封装字段的简单数据对象,由于只设置字段,因此初始化它的成本很低。

相比之下,添加到列表中比通过网络套接字发送相同数量的数据要慢得多。这没有任何意义,因为本地操作应该总是比网络相关的操作快得多。

1 million元素在大约0.2 seconds时间内完成,但67 million甚至不会在合理的时间内完成。它最多应该在几秒钟内完成。

代码语言:javascript
运行
复制
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class ListPerformanceTester
{
    public enum ValueSize
    {
        EIGHT_BIT("8-Bit"),
        SIXTEEN_BIT("16-Bit"),
        THIRTY_TWO_BIT("32-Bit"),
        SIXTY_FOUR_BIT("64-Bit"),
        NINETY_SIX_BIT("96-Bit");

        private String name;

        ValueSize(String name)
        {
            this.name = name;
        }

        public int getBytesCount()
        {
            switch (this)
            {
                case EIGHT_BIT:
                    return 1;

                case SIXTEEN_BIT:
                    return 2;

                case THIRTY_TWO_BIT:
                    return 4;

                case SIXTY_FOUR_BIT:
                    return 8;

                case NINETY_SIX_BIT:
                    return 12;
            }

            throw new IllegalStateException("Bytes count undefined for " + this);
        }

        @Override
        public String toString()
        {
            return name;
        }

        public static ValueSize parse(String name)
        {
            ValueSize[] valueSizes = values();

            for (ValueSize valueSize : valueSizes)
            {
                String currentName = valueSize.toString();

                if (currentName.equals(name))
                {
                    return valueSize;
                }
            }

            throw new IllegalArgumentException("No value size associated");
        }
    }

    public static class SearchResult implements Cloneable, Comparable
    {
        private int address;
        private ValueSize valueSize;
        private BigInteger previousValue;
        private BigInteger currentValue;
        private BigInteger valueDifference;

        public SearchResult(int address, BigInteger previousValue,
                            BigInteger currentValue, ValueSize valueSize)
        {
            this.address = address;
            this.valueSize = valueSize;
            this.previousValue = previousValue;
            this.currentValue = currentValue;

            setValueDifference();
        }

        private void setValueDifference()
        {
            BigInteger subtractionResult = previousValue.subtract(currentValue);
            valueDifference = subtractionResult.abs();
        }

        private byte[] getBytes(BigInteger bigInteger) throws IOException
        {
            byte[] retrieved = bigInteger.toByteArray();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int bytesCount = getValueSize().getBytesCount();
            int paddingBytes = bytesCount - retrieved.length;

            if (paddingBytes >= 0)
            {
                byteArrayOutputStream.write(new byte[paddingBytes]);
                byteArrayOutputStream.write(retrieved);
            } else
            {
                writeWithoutLeadingNullBytes(byteArrayOutputStream, retrieved);
            }

            return byteArrayOutputStream.toByteArray();
        }

        private void writeWithoutLeadingNullBytes(ByteArrayOutputStream byteArrayOutputStream, byte[] bytes)
        {
            int index = 0;
            boolean nonNullByteFound = false;

            while (index < bytes.length)
            {
                byte value = bytes[index];

                if (value != 0 || nonNullByteFound)
                {
                    nonNullByteFound = true;
                    byteArrayOutputStream.write(value);
                }

                index++;
            }
        }

        public int getAddress()
        {
            return address;
        }

        @Override
        public boolean equals(Object object)
        {
            if (!(object instanceof SearchResult))
            {
                return false;
            }

            SearchResult searchResult = (SearchResult) object;

            return searchResult.getAddress() == getAddress();
        }

        @Override
        public int hashCode()
        {
            return Integer.hashCode(address);
        }

        public ValueSize getValueSize()
        {
            return valueSize;
        }

        @Override
        public SearchResult clone()
        {
            return new SearchResult(address, previousValue, currentValue, valueSize);
        }

        @Override
        public int compareTo(Object object)
        {
            return new Integer(address).compareTo(((SearchResult) object).getAddress());
        }
    }

    public static void main(String[] arguments)
    {
        long milliseconds = System.currentTimeMillis();
        int elementsCount = 2000000;

        /*List<Integer> list = new ArrayList<>();

        for (int elementIndex = 0; elementIndex < elementsCount; elementIndex++)
        {
            list.add(0);
        }*/

        List<SearchResult> searchResults = new ArrayList<>();

        for (int elementIndex = 0; elementIndex < elementsCount; elementIndex++)
        {
            SearchResult searchResult = new SearchResult(0x12345678, new BigInteger("3"), new BigInteger("1"), ValueSize.EIGHT_BIT);
            searchResults.add(searchResult);
        }

        System.out.println((System.currentTimeMillis() - milliseconds) / (double) 1000 + " seconds");
    }
}

这里最大的问题是什么?

EN

回答

页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41411365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档