Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/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 Hashset与Treeset_Java_Hashset_Treeset - Fatal编程技术网

Java Hashset与Treeset

Java Hashset与Treeset,java,hashset,treeset,Java,Hashset,Treeset,我一直很喜欢树,那漂亮的O(n*log(n))和它们的整洁。然而,我认识的每一位软件工程师都尖锐地问我为什么要使用TreeSet。从CS的背景来看,我认为你使用什么并不重要,我也不想乱弄散列函数和存储桶(在Java的情况下) 在哪种情况下,我应该在树集上使用哈希集?哈希集是O(1)来访问元素,所以它当然很重要。但维护集合中对象的顺序是不可能的 TreeSet如果维护顺序(以值而不是插入顺序)对您来说很重要,那么它很有用。但是,正如您所注意到的,您正在用较慢的时间来访问一个元素:O(logn)进行

我一直很喜欢树,那漂亮的
O(n*log(n))
和它们的整洁。然而,我认识的每一位软件工程师都尖锐地问我为什么要使用
TreeSet
。从CS的背景来看,我认为你使用什么并不重要,我也不想乱弄散列函数和存储桶(在
Java
的情况下)

在哪种情况下,我应该在
树集上使用
哈希集

哈希集
是O(1)来访问元素,所以它当然很重要。但维护集合中对象的顺序是不可能的

TreeSet
如果维护顺序(以值而不是插入顺序)对您来说很重要,那么它很有用。但是,正如您所注意到的,您正在用较慢的时间来访问一个元素:O(logn)进行基本操作

从:

此实现为基本操作(
添加
删除
包含
)提供了保证的日志(n)时间成本


如果您没有插入足够的元素,导致频繁的重置(或冲突,如果您的哈希集无法调整大小),哈希集肯定会为您提供恒定时间访问的好处。但是在有大量增长或收缩的集合上,根据实现的不同,使用树集合实际上可能会获得更好的性能


如果我记性好的话,一棵功能性红黑树的摊销时间可以接近O(1)。冈崎的书会有一个比我更好的解释。(或参见)

当然,HashSet实现要快得多——因为不需要排序,所以开销更小。有关Java中各种集合实现的详细分析,请参阅


这里的讨论还指出了一个有趣的“中间地带”方法来解决树与散列问题。Java提供了一个LinkedHashSet,它是一个哈希集,其中运行着一个“面向插入”的链表,也就是说,链表中的最后一个元素也是最近插入到哈希中的元素。这允许您避免无序散列的无序性,而不会增加树集的成本

大多数使用HashSet的原因是(平均)操作是O(1)而不是O(logn)。如果集合包含标准项,则不会像为您所做的那样“胡乱使用哈希函数”。如果集合包含自定义类,则必须实现
hashCode
才能使用
HashSet
(虽然有效的Java演示了如何使用),但如果使用
TreeSet
,则必须使其具有
可比性
或提供
比较器。如果类没有特定的顺序,这可能是一个问题

我有时会将
TreeSet
(或者实际上是
TreeMap
)用于非常小的集合/地图(<10项),尽管我没有检查这样做是否有任何实际好处。对于大型集合,差异可能相当大


现在,如果您需要排序,则
树集
是合适的,尽管即使如此,如果更新频繁且不经常需要排序结果,有时将内容复制到列表或数组并对其进行排序会更快。

消息编辑(完全重写)当顺序不重要时,也就是此时。两者都应该给出Log(n)-这将有助于查看其中一个是否比另一个快5%。HashSet可以在循环中给出O(1)测试,这应该可以揭示它是否是。

树集是两个排序集合之一(另一个是 树形图)。它使用红黑树结构(但您知道),并保证 元素将按照自然顺序以升序排列。或者, 您可以使用构造函数构造树集,该构造函数允许您为集合指定 自己的订单规则(而不是依赖于定义的订单 通过使用可比较的或比较器(根据元素的类别)

LinkedHashSet是一个有序的HashSet版本 跨所有元素维护双链接列表。使用这个类而不是HashSet 当您关心迭代顺序时。当您遍历哈希集时 顺序是不可预测的,而LinkedHashSet允许您遍历元素
按照插入顺序,HashSet比TreeSet快得多(对于大多数操作,如添加、删除和包含,固定时间与日志时间),但不提供TreeSet的排序保证。

  • 该类为基本操作(添加、删除、包含和大小)提供恒定的时间性能
  • 它不能保证元素的顺序随时间保持不变
  • 迭代性能取决于哈希集的初始容量和负载因子。
    • 接受默认的负载系数是非常安全的,但是您可能希望指定一个初始容量,该容量大约是您期望该集增长到的大小的两倍
  • 保证基本操作(添加、删除和包含)的日志(n)时间成本
  • 保证集合的元素将被排序(升序、自然或您通过其构造函数指定的元素)(实现)
  • 不为迭代性能提供任何调优参数
  • 提供了一些方便的方法来处理有序集,如,
    last()
要点:
  • 两者都保证元素的重复自由收集
  • 通常,将元素添加到HashSet,然后将集合转换为树集以进行重复的自由排序遍历会更快
  • 这些实现都不是同步的。也就是说,如果多个线程同时访问一个集合,并且至少有一个线程修改该集合,则必须在外部对其进行同步
  • LinkedHashSet在某种意义上介于
    HashSet
    import java.util.HashSet;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class HashTreeSetCompare {
    
        //It is generally faster to add elements to the HashSet and then
        //convert the collection to a TreeSet for a duplicate-free sorted
        //Traversal.
    
        //really? 
        O(Hash + tree set) > O(tree set) ??
        Really???? Why?
    
    
    
        public static void main(String args[]) {
    
            int size = 80000;
            useHashThenTreeSet(size);
            useTreeSetOnly(size);
    
        }
    
        private static void useTreeSetOnly(int size) {
    
            System.out.println("useTreeSetOnly: ");
            long start = System.currentTimeMillis();
            Set<String> sortedSet = new TreeSet<String>();
    
            for (int i = 0; i < size; i++) {
                sortedSet.add(i + "");
            }
    
            //System.out.println(sortedSet);
            long end = System.currentTimeMillis();
    
            System.out.println("useTreeSetOnly: " + (end - start));
        }
    
        private static void useHashThenTreeSet(int size) {
    
            System.out.println("useHashThenTreeSet: ");
            long start = System.currentTimeMillis();
            Set<String> set = new HashSet<String>();
    
            for (int i = 0; i < size; i++) {
                set.add(i + "");
            }
    
            Set<String> sortedSet = new TreeSet<String>(set);
            //System.out.println(sortedSet);
            long end = System.currentTimeMillis();
    
            System.out.println("useHashThenTreeSet: " + (end - start));
        }
    }
    
     TreeSet<String> ts = new TreeSet<String>();
     ts.add(null); // throws NullPointerException
    
     HashSet<String> hs = new HashSet<String>();
     hs.add(null); // runs fine
    
    ╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
    ║   Property   ║       HashSet       ║      TreeSet      ║     LinkedHashSet   ║
    ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
    ║              ║  no guarantee order ║ sorted according  ║                     ║
    ║   Order      ║ will remain constant║ to the natural    ║    insertion-order  ║
    ║              ║      over time      ║    ordering       ║                     ║
    ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
    ║ Add/remove   ║        O(1)         ║     O(log(n))     ║        O(1)         ║
    ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
    ║              ║                     ║   NavigableSet    ║                     ║
    ║  Interfaces  ║         Set         ║       Set         ║         Set         ║
    ║              ║                     ║    SortedSet      ║                     ║
    ╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
    ║              ║                     ║    not allowed    ║                     ║
    ║  Null values ║       allowed       ║ 1st element only  ║      allowed        ║
    ║              ║                     ║     in Java 7     ║                     ║
    ╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
    ║              ║   Fail-fast behavior of an iterator cannot be guaranteed      ║
    ║   Fail-fast  ║ impossible to make any hard guarantees in the presence of     ║
    ║   behavior   ║           unsynchronized concurrent modification              ║
    ╠══════════════╬═══════════════════════════════════════════════════════════════╣
    ║      Is      ║                                                               ║
    ║ synchronized ║              implementation is not synchronized               ║
    ╚══════════════╩═══════════════════════════════════════════════════════════════╝
    
    TreeSet<String> treeSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
    HashSet<String> hashSet = new HashSet<>();
    treeSet.add("a");
    hashSet.add("A");
    System.out.println(hashSet.equals(treeSet));
    System.out.println(treeSet.equals(hashSet));