Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是添加到集合然后对其排序更快,还是添加到已排序的集合更快?_Java_Sorting_Collections - Fatal编程技术网

Java 是添加到集合然后对其排序更快,还是添加到已排序的集合更快?

Java 是添加到集合然后对其排序更快,还是添加到已排序的集合更快?,java,sorting,collections,Java,Sorting,Collections,如果我有一张这样的地图: HashMap<Integer, ComparableObject> map; (B) 创建有序集合的实例,如TreeSet,然后添加值: Set<ComparableObject> sortedCollection = new TreeSet<ComparableObject>(map.values()); Set sortedCollection=new TreeSet(map.values()); 请注意,生成的集合永远不

如果我有一张这样的
地图

HashMap<Integer, ComparableObject> map;
(B) 创建有序集合的实例,如
TreeSet
,然后添加值:

Set<ComparableObject> sortedCollection = new TreeSet<ComparableObject>(map.values());
Set sortedCollection=new TreeSet(map.values());

请注意,生成的集合永远不会被修改,因此排序只需要进行一次。

理论上,最后的排序应该更快。 在整个进程中维护排序状态可能需要额外的CPU时间

从CS的角度来看,这两个操作都是NlogN,但1个排序应该具有较低的常数。

TreeSet具有
log(n)
时间复杂性保证,用于
add()/remove()/contains()
方法。 排序
ArrayList
需要
n*log(n)
操作,但是
add()/get()
只需要
1
操作


因此,如果您主要是检索,而不经常排序,
ArrayList
是更好的选择。如果您经常排序,但没有检索到那么多
TreeSet
将是一个更好的选择。

如果您选择实现B),请务必阅读我在底部对TreeSet的评论

如果你的应用程序只是偶尔进行排序,但经常重复,我认为你最好使用一个简单的未排序列表。对它进行一次排序,然后从更快的迭代中获益。迭代在数组列表上特别快

但是,如果您希望始终保证排序顺序,或者您可能经常添加/删除元素,那么就使用排序集合,并在迭代中获得成功

所以在你的情况下,我会说A)是更好的选择。该列表只排序一次,不会更改,因此作为一个数组很有好处。迭代应该非常快,特别是如果您知道它是ArrayList,并且可以直接使用ArrayList.get()而不是迭代器


我还要补充一点,树集的定义是一个集合,这意味着对象是唯一的。树集通过在Comparator/Comparable上使用compareTo来确定相等性。如果尝试添加两个compareTo返回值为0的对象,则很容易发现自己缺少数据。e、 g.在树集合中添加“C”、“A”、“B”、“A”将返回“A”、“B”、“C”

为什么不同时使用这两个世界中的最好的一个呢?若不再使用它,请使用树集进行排序,并使用内容初始化ArrayList

List<ComparableObject> sortedCollection = 
    new ArrayList<ComparableObject>( 
          new TreeSet<ComparableObject>(map.values()));
奇怪的是,我的方法在迭代中表现最好(我原以为迭代中与ArrayList方法没有区别,我的基准测试中有bug吗?)

免责声明:我知道这可能是一个糟糕的基准,但它有助于让您理解这一点,我当然没有操纵它以使我的方法获胜


(对于equals/hashcode/compareTo构建器,代码依赖于apache commons/lang,但重构起来应该很容易)

集合。sort
使用带有O(nlog n)的mergeSort

TreeSet
具有红黑树底层,基本操作具有O(logn)。因此n个元素也有O(nlogn)


因此,这两种算法都是相同的大O算法。

在一个分类数据集中插入的是O(log(n))(但是!是当前的n,而不是最终的n)。 在列表中插入是1

插入中已包含SortedSet中的排序,因此为0。 列表中的排序是O(n*log(n))

因此,除最后一种情况外,所有情况下的SortedSet总复杂度都是O(n*k),k 因此,SortedSet在数学上具有最佳性能。但最终,您得到的是一个集合而不是一个列表(因为SortedList不存在),并且集合提供的功能比列表少。 因此,在我看来,针对可用功能和性能的最佳解决方案是Sean Patrick Floyd提出的:

  • 使用分类数据集进行插入
  • 将SortedSet作为创建要返回的列表的参数

    • 好问题,好答案。我只是想补充几点考虑:

    • 例如,如果要排序的集合是短期的,用作方法的参数,并且需要在方法中对列表进行排序,则使用Collections.sort(Collection)。或者,如果它是长寿命对象,但您需要很少对其进行排序
    • 理由:排序后的集合是特定内容所必需的,您可能不会经常添加或删除。因此,在对集合进行排序后,您并不真正关心集合中的元素。你基本上:

      排序->使用它->忘记

      如果向已排序的集合中添加新元素,则必须再次对集合进行排序,因为插入新元素时不能保证顺序

    • 如果要排序的集合是长期存在的,并且/或者如果它是类中的一个字段,并且您需要始终对其进行排序,那么您应该使用排序数据结构,例如TreeSet
    • 理由:您始终关心收款顺序。您希望随时对其进行排序。因此,如果不断添加或删除元素,则可以保证集合已排序。所以基本上:

      插入/删除->使用它(只要您保证集合已排序)

      没有特定的时刻需要对集合进行排序,相反,您希望始终对集合进行排序

      使用TreeSet的缺点是它需要保留已排序集合的资源。它使用红黑树,并且get、put操作需要O(logn)时间开销


      而如果使用简单的集合,例如ArrayList,则get、add操作是O(1)恒定时间。

      这取决于输入数据的顺序-例如,如果您提取了很多行并使用了顺序,那么这是一种情况-如果您有一组随机的GUID-另一种情况。为什么不使用树形图呢?树形图在这里没有帮助,因为需要对值(
      ComparableObjectList<ComparableObject> sortedCollection = 
          new ArrayList<ComparableObject>( 
                new TreeSet<ComparableObject>(map.values()));
      
      compareTo() calls:123490
      Transformer ArrayListTransformer
          Creation: 255885873 ns (0.255885873 seconds) 
          Iteration: 2582591 ns (0.002582591 seconds) 
          Item count: 10000
      
      compareTo() calls:121665
      Transformer TreeSetTransformer
          Creation: 199893004 ns (0.199893004 seconds) 
          Iteration: 4848242 ns (0.004848242 seconds) 
          Item count: 10000
      
      compareTo() calls:121665
      Transformer BestOfBothWorldsTransformer
          Creation: 216952504 ns (0.216952504 seconds) 
          Iteration: 1604604 ns (0.001604604 seconds) 
          Item count: 10000
      
      compareTo() calls:18819
      Transformer PriorityQueueTransformer
          Creation: 35119198 ns (0.035119198 seconds) 
          Iteration: 2803639 ns (0.002803639 seconds) 
          Item count: 10000