Java 集合相互之间的性能如何?

问题描述 投票:0回答:1

所以在编程讲座中,讲师给了我们一些关于一些Java Collections的性能的数据。他使用了这篇文章中给出的数据。.

然后我和我的伙伴决定亲自测试一下。但我们的测量结果与帖子中给出的结果有很大不同。我们测试了下面列出的集合的“添加”、“包含”、“删除”和“清除”。里面还放了几张地图。

哈希集 树集 链接哈希集 数组列表 链表 数组双端队列 优先队列 哈希映射 树形图 LinkedHashMap

这是我们的代码。我们进行 100 次测试并计算平均值。

import java.util.*; public class Testing { public void initializeAndRun(int testCases){ Set<Integer> hashSet = new HashSet<>(); Set<Integer> treeSet = new TreeSet<>(); Set<Integer> linkedHashSet = new LinkedHashSet<>(); List<Integer> linkedList = new LinkedList<>(); List<Integer> arrayList = new ArrayList<>(); Queue<Integer> priorityQueue = new PriorityQueue<>(); Queue<Integer> arrayDeque = new ArrayDeque<>(); Map<Integer, Integer> hashMap = new HashMap<>(); Map<Integer, Integer> treeMap = new TreeMap<>(); Map<Integer, Integer> linkedHashMap = new LinkedHashMap<>(); testSet(hashSet, "Hash Set","add", testCases); testSet(treeSet, "Tree Set","add", testCases); testSet(linkedHashSet, "Linked Hash Set", "add", testCases); testList(linkedList, "Linked List", "add", testCases); testList(arrayList, "Array List", "add", testCases); testQueue(priorityQueue, "Priority Queue", "add", testCases); testQueue(arrayDeque, "Array Deque", "add", testCases); testMap(hashMap, "Hash Map", "add", testCases); testMap(treeMap, "Tree Map", "add", testCases); testMap(linkedHashMap, "Linked Hash Map", "add", testCases); System.out.println(); testSet(hashSet, "Hash Set","contains", testCases); testSet(treeSet, "Tree Set","contains", testCases); testSet(linkedHashSet, "Linked Hash Set", "contains", testCases); testList(linkedList, "Linked List", "contains", testCases); testList(arrayList, "Array List", "contains", testCases); testQueue(priorityQueue, "Priority Queue", "contains", testCases); testQueue(arrayDeque, "Array Deque", "contains", testCases); testMap(hashMap, "Hash Map", "contains", testCases); testMap(treeMap, "Tree Map", "contains", testCases); testMap(linkedHashMap, "Linked Hash Map", "contains", testCases); System.out.println(); testSet(hashSet, "Hash Set","remove", testCases); testSet(treeSet, "Tree Set","remove", testCases); testSet(linkedHashSet, "Linked Hash Set", "remove", testCases); testList(linkedList, "Linked List", "remove", testCases); testList(arrayList, "Array List", "remove", testCases); testQueue(priorityQueue, "Priority Queue", "remove", testCases); testQueue(arrayDeque, "Array Deque", "remove", testCases); testMap(hashMap, "Hash Map", "remove", testCases); testMap(treeMap, "Tree Map", "remove", testCases); testMap(linkedHashMap, "Linked Hash Map", "remove", testCases); System.out.println(); testSet(hashSet, "Hash Set","clear", testCases); testSet(treeSet, "Tree Set","clear", testCases); testSet(linkedHashSet, "Linked Hash Set", "clear", testCases); testList(linkedList, "Linked List", "clear", testCases); testList(arrayList, "Array List", "clear", testCases); testQueue(priorityQueue, "Priority Queue", "clear", testCases); testQueue(arrayDeque, "Array Deque", "clear", testCases); testMap(hashMap, "Hash Map", "clear", testCases); testMap(treeMap, "Tree Map", "clear", testCases); testMap(linkedHashMap, "Linked Hash Map", "clear", testCases); System.out.println(); } private void loadSet(Set<Integer> input){ input.clear(); Random randInt = new Random(); for(int i = 0; i < 100000; i++){ Integer x = randInt.nextInt(100000); input.add(x); } } private void loadList(List<Integer> input){ input.clear(); Random randInt = new Random(); for(int i = 0; i < 100000; i++){ Integer x = Integer.valueOf(randInt.nextInt(100000)); input.add(x); } } private void loadQueue(Queue<Integer> input){ input.clear(); Random randInt = new Random(); for(int i = 0; i < 100000; i++){ Integer x = Integer.valueOf(randInt.nextInt(100000)); input.add(x); } } private void loadMap(Map<Integer, Integer> input){ input.clear(); Random randInt = new Random(); for(int i = 0; i < 100000; i++){ Integer x = Integer.valueOf(randInt.nextInt(100000)); input.put(x, x); } } private void testSet(Set<Integer> input, String name, String test, int testNo){ long totalTime = 0; long start = 0; long end = 0; Random rand = new Random(); for(int i = 0; i < testNo; i++){ loadSet(input); Integer x = Integer.valueOf(rand.nextInt(10000)); if(test.equals("add")) { start = System.nanoTime(); input.add(x); end = System.nanoTime(); input.remove(x); }else if(test.equals("contains")){ start = System.nanoTime(); input.contains(x); end = System.nanoTime(); }else if(test.equals("remove")){ Object[] array = input.toArray(); int index = rand.nextInt(array.length); int element = (int) array[index]; start = System.nanoTime(); input.remove(element); end = System.nanoTime(); input.add(element); }else if(test.equals("clear")){ start = System.nanoTime(); input.clear(); end = System.nanoTime(); } totalTime += end - start; } long averageTime = totalTime/testNo; printResult(name, test, averageTime); } private void testList(List<Integer> input, String name, String test, int testNo){ long totalTime = 0; long start = 0; long end = 0; Random rand = new Random(); for(int i = 0; i < testNo; i++){ loadList(input); Integer x = Integer.valueOf(rand.nextInt(10000)); if(test.equals("add")) { start = System.nanoTime(); input.add(x); end = System.nanoTime(); input.remove(x); }else if(test.equals("contains")){ start = System.nanoTime(); input.contains(x); end = System.nanoTime(); }else if(test.equals("remove")){ Object[] array = input.toArray(); int index = rand.nextInt(array.length); int element = (int) array[index]; start = System.nanoTime(); input.remove(element); end = System.nanoTime(); input.add(element); }else if(test.equals("clear")){ start = System.nanoTime(); input.clear(); end = System.nanoTime(); } totalTime += end - start; } long averageTime = totalTime/testNo; printResult(name, test, averageTime); } private void testQueue(Queue<Integer> input, String name, String test, int testNo){ long totalTime = 0; long start = 0; long end = 0; Random rand = new Random(); for(int i = 0; i < testNo; i++){ loadQueue(input); Integer x = Integer.valueOf(rand.nextInt(10000)); if(test.equals("add")) { start = System.nanoTime(); input.add(x); end = System.nanoTime(); input.remove(x); }else if(test.equals("contains")){ start = System.nanoTime(); input.contains(x); end = System.nanoTime(); }else if(test.equals("remove")){ Object[] array = input.toArray(); int index = rand.nextInt(array.length); int element = (int) array[index]; start = System.nanoTime(); input.remove(element); end = System.nanoTime(); input.add(element); }else if(test.equals("clear")){ start = System.nanoTime(); input.clear(); end = System.nanoTime(); } totalTime += end - start; } long averageTime = totalTime/testNo; printResult(name, test, averageTime); } private void testMap(Map<Integer, Integer> input, String name, String test, int testNo){ long totalTime = 0; long start = 0; long end = 0; Random rand = new Random(); for(int i = 0; i < testNo; i++){ loadMap(input); Integer x = Integer.valueOf(rand.nextInt(10000)); if(test.equals("add")) { start = System.nanoTime(); input.put(x, x); end = System.nanoTime(); input.remove(x, x); }else if(test.equals("contains")){ start = System.nanoTime(); input.containsKey(x); end = System.nanoTime(); }else if(test.equals("remove")){ Set<Integer> keysSet = input.keySet(); Integer[] array = new Integer[keysSet.size()]; keysSet.toArray(array); int index = rand.nextInt(array.length); int element = (int) array[index]; start = System.nanoTime(); input.remove(element); end = System.nanoTime(); input.put(element, element); }else if(test.equals("clear")){ start = System.nanoTime(); input.clear(); end = System.nanoTime(); } totalTime += end - start; } long averageTime = totalTime/testNo; printResult(name, test, averageTime); } private void printResult(String name, String test, long averageTime){ System.out.printf("%s: %s: %d ns%n", name,test, averageTime); } public static void main(String[] args){ Testing test = new Testing(); int testCases = 100; test.initializeAndRun(testCases); } }
它给出了以下输出:
哈希集:添加:225 ns

树集:添加:430 ns

链接哈希集:添加:46 ns

链表:添加:61 ns

数组列表:添加:33 ns

优先级队列:添加:45 ns

数组双端队列:添加:55 ns

哈希映射:添加:40 ns

树图:添加:166 ns

链接哈希图:添加:43 ns

哈希集:包含:235 ns

树集:包含:456 ns

链接哈希集:包含:57 ns

链接列表:包含:163147 ns

数组列表:包含:45355 ns

优先级队列:包含:35929 ns

数组双端队列:包含:53337 ns

哈希映射:包含:90 ns

树图:包含:380 ns

链接哈希图:包含:51 ns

哈希集:删除:506 ns

树集:删除:1236 ns

链接哈希集:删除:150 ns

链表:删除:54833 ns

数组列表:删除:16115 ns

优先级队列:删除:31837 ns

数组双端队列:删除:35739 ns

哈希映射:删除:110 ns

树图:删除:823 ns

链接哈希图:删除:129 ns

哈希集:清除:32998 ns

树集:清晰:322 ns

链接哈希集:清除:33273 ns

链接列表:清除:213397 ns

数组列表:清除:24334 ns

优先级队列:清除:25343 ns

数组双端队列:清除:45598 ns

哈希映射:清除:33457 ns

树图:清晰:27 ns

链接哈希图:清除:33289 ns

如您所见,与其他结果相比,TreeSet 上的“清晰”结果与讲座中给出的值(帖子中的值)完全不匹配。

我们做错了什么吗?我的意思是,我们必须如此!它是什么?请问有什么帮助吗?

我们尝试编写自己的代码,如上所示。我们看了很长时间,但什么也没弄清楚。请记住,我们是初级 Java 程序员;只学习了3周。

java collections time-complexity computer-science abstract-data-type
1个回答
0
投票
我们做错了什么吗?我的意思是,我们必须如此!它是什么?请问有什么帮助吗?

为什么?您链接到的帖子没有代码来验证其结果。它甚至没有列出运行测试的 JVM 和架构。

TreeSet.clear 速度很快。至少,它是在 JDK21 上;我没有看过早期版本,但是,我很确定它

总是以这种方式工作:

  • TreeSet
     没什么 - 它只是创建一个 
    TreeMap
     并将每个调用降级到地图。该映射中的键是树集中的值;这些值是无关紧要的(
    PRESENT
     - 单个
    new Object()
    只是为了有一些“值”来映射这些键)。
  • 因此
  • ts.clear()
     只需调用 TreeSet 所构建的地图的 
    clear()
     方法。
  • TreeMap 的clear 做了 3 件事:它更新一个指针(将单个单词写入一个字段),它递增一个 int 字段,并将另一个 int 字段设置为 0。换句话说,它读入其中一个字段,然后写入3 个领域。这是一个单一的缓存页面操作,在具有足够管道能力的 CPU 上运行大约 1 个时钟周期(即除了手机 CPU 和树莓派之外的所有 CPU)。很难想象还有比这更快的了。
因此,“TreeSet.clear 很慢”完全是马粪,而链接到的中等文章没有代码,没有关于如何编写或运行该代码的详细信息,并且至少有一个令人难以置信的可疑结果,

应该是完全无视.

您应该引导您的教授解决这个问题,并确保他们不再将这些问题传播给未来的学生。你的同学/未来的学生谢谢你!

© www.soinside.com 2019 - 2024. All rights reserved.