Java中的小集合:哪种数据结构?

Java中的小集合:哪种数据结构?,java,set,Java,Set,关于small集合(比如1-100个元素)上的各种Java集合实现的性能,有没有什么好的参考资料,或者有人可以告诉我更多?O(1)vs O(logn)的故事与这些大小几乎无关,但由于我需要处理数百万个这样的小集合,性能当然很重要。我找到的大多数参考资料都没有提到这一点 我需要对这些设备执行以下操作(通常每套仅执行几次): 初始化新集和/或硬拷贝旧集 添加/删除元素 在集合上迭代 计算整个集合的hashCode() 我认为这些是比较可行的选项(假设比较/哈希T几乎是免费的): HashSet

关于small集合(比如1-100个元素)上的各种Java集合实现的性能,有没有什么好的参考资料,或者有人可以告诉我更多?O(1)vs O(logn)的故事与这些大小几乎无关,但由于我需要处理数百万个这样的小集合,性能当然很重要。我找到的大多数参考资料都没有提到这一点

我需要对这些设备执行以下操作(通常每套仅执行几次):

  • 初始化新集和/或硬拷贝旧集
  • 添加/删除元素
  • 在集合上迭代
  • 计算整个集合的
    hashCode()
我认为这些是比较可行的选项(假设比较/哈希T几乎是免费的):

  • HashSet:似乎不擅长迭代(因此在
    hashCode()
  • 树集:似乎开销高得离谱
  • LinkedHashSet:完全没有这方面的经验,它的开销高吗
  • ArrayList:本身很快,但不是一组,所以需要像
    Collections.sort()这样丑陋的技巧。

以上哪一项通常是首选的?或者我应该编写自己的
SmallSet
类吗?

如果您真的在寻找性能,那么除了为自己测试之外,没有什么能帮助您:

  • 您是否经常为其分配新的资源?如果是这样,垃圾收集可能比其他情况更相关
  • 您是否只分配了一次,并且需要快速访问?哈希冲突将对此产生影响
  • 你在不断地改变它们吗
您需要设置一个与您的实际使用测试相似的测试用例,其时间足够长,以便GC启动,您可以看到其中的效果

如果您检测到它们之间的关键差异,那么在JVM的每次更新之后都会重新运行测试,因为实现可能会发生变化


在您完成此类性能测试之前,我将给出我的标准建议:选择可读性最好的选项,并且仅当使用可读性较差的选项有明显好处时才进行更改。代码维护人员(可能是未来的您)会为此感谢您。

这是一个小型阵列实现:

很容易适应您的需要:)

资料来源:

公共类数组集{
私有int[]数组;
私有整数大小=0;
公共阵列集(内部容量){
数组=新整数[容量];
数组。填充(数组,-1);
}
公共布尔加法(整数键){
int index=Arrays.binarySearch(数组,0,大小,键);
如果(指数<0){
int insertIndex=-index-1;
if(大小<数组长度-1){
如果(插入索引<大小){
System.arraycopy(数组,insertIndex,数组,insertIndex+1,大小-insertIndex);
}
数组[insertIndex]=键;
}否则{
int[]newArray=newint[array.length+1];
System.arraycopy(数组,0,newArray,0,insertIndex);
System.arraycopy(array,insertIndex,newArray,insertIndex+1,array.length-insertIndex);
newArray[insertIndex]=键;
数组=新数组;
}
大小++;
返回true;
}
返回false;
}
公共整数获取(整数位置){
返回数组[位置];
}
公共整数大小(){
返回大小;
}
公共布尔包含(int键){
返回数组。二进制搜索(数组,键)>=0;
}
}

如果你真的只有十个可能的元素,这里还有一个:
boolean[]
。不,集合本身的大小很小,但它们的内容可以是T类型的任何对象,并且可能有成千上万个不同的对象。所以,<代码>布尔[]/COD>,<代码> BITSET 或任何类似的,绝对不是一个选项。除非你进入了过早的优化,而且它是至关重要的,所以你应该考虑JNI的高达。@ JONASBYSTR OM——你的评论对我来说毫无意义。1) 过早优化是关于优化的决定,而不是你使用的技术。2) 对于“对象集”类型,JNI将是一个糟糕的优化选择。考虑到在Java对象上调用方法时必须在JNI中跳转,等等,如果本机代码实现实际上比Java实现慢,我不会感到惊讶。。。包括实际了解JNI的工作原理,以及实际了解通过JNI在本机代码中实现可行的Java对象数据结构集所需的内容。如果你认为我错了,证明一下。实现它,并证明它比相同API的等效纯Java实现更快。您从测试中看到了什么?
public class ArraySet {
    private int[] array;
    private int size = 0;

    public ArraySet(int capacity) {
        array = new int[capacity];
        Arrays.fill(array, -1);
    }

    public boolean add(int key) {
        int index = Arrays.binarySearch(array, 0, size, key);
        if (index < 0) {
            int insertIndex = -index-1;

            if(size < array.length - 1) {
                if(insertIndex < size) {
                    System.arraycopy(array, insertIndex, array, insertIndex + 1, size - insertIndex);
                }
                array[insertIndex] = key;
            } else {
                int[] newArray = new int[array.length + 1];
                System.arraycopy(array, 0, newArray, 0, insertIndex);
                System.arraycopy(array, insertIndex, newArray, insertIndex + 1, array.length - insertIndex);
                newArray[insertIndex] = key;
                array = newArray;
            }

            size++;
            return true;
        }
        return false;
    }

    public int get(int position) {
        return array[position];
    }

    public int size() {
        return size;
    }

    public boolean contains(int key) {
        return Arrays.binarySearch(array, key) >= 0;
    }
}