-
TreeSet 的 contains 问题10
import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; public class TreeSetTest { public void testCompare(){ Map<String,String> m1 = new HashMap<String,String>(); m1.put("AC029", "SE.mg"); Map<String,String> m2 = new HashMap<String,String>(); m2.put("OS05M", "USD"); Map<String,String> m3 = new HashMap<String,String>(); m3.put("OS01W", "Stratic Energy Corp"); m3.put("OS001", "SE"); m3.put("LS01Z", "EX$$$$XTSX"); m3.put("OS06Y", "0P00005RTY"); m3.put("AA0B5", "0C00000KDB"); m3.put("ST735", "IG000DA093"); Map<String,String> m4 = new HashMap<String,String>(); m4.put("OS01W", "Spectra Energy Corp"); m4.put("OS05K", "847560109"); Map<String,String> m5 = new HashMap<String,String>(); m5.put("OS01W","Spectra Energy Corp"); m5.put("OS05K","847560109"); m5.put("OS05J","US8475601097"); m5.put("AA0B5","0C00000MIG"); m5.put("IT152","309"); m5.put("AA0F4","3"); m5.put("ST735","IG000DA096"); m5.put("OS05M","USD"); Map<String,String> m6 = new HashMap<String,String>(); m6.put("OS01W","Spectra Energy Corp"); m6.put("OS05K","847560109"); m6.put("LS01Z","EX$$$$XNYS"); m6.put("OS00I","0P00007KRO"); m6.put("AC020","SPECTRA ENERGY Corp"); m6.put("AA0B5","0C00000MIG"); m6.put("ST735","IG000DA096"); Map<String,String> m7 = new HashMap<String,String>(); m7.put("OS01W","Spectra Energy Corp"); m7.put("OS05K","847560109"); m7.put("AC020","SPECTRA ENERGY Corp"); m7.put("AA0B5","0C00000MIG"); m7.put("ST735","IG000DA096"); Map<String,String> m8 = new HashMap<String,String>(); m8.put("OS01W","Spectra Energy Corp"); m8.put("OS05K","847560109"); m8.put("LS01Z","EX$$$$XNYS"); m8.put("AA0B5","0C00000MIG"); m8.put("ST735","IG000DA096"); m8.put("OS05M","USD"); Set<Map<String,String>> set = new TreeSet<Map<String,String>>(new HashCompare()); set.add(m1); set.add(m2); set.add(m3); set.add(m4); set.add(m5); set.add(m6); set.add(m7); set.add(m8); System.out.println(set.contains(m3)); } class HashCompare implements Comparator{ public int compare(Object o1, Object o2) { return o1.hashCode() - o2.hashCode(); } } public static void main(String[] args) { TreeSetTest ts = new TreeSetTest(); ts.testCompare(); } }
2014年9月17日 18:33
3个答案 按时间排序 按投票排序
-
采纳的答案
首先treeset的contains方法
使用的是Treemap的containskey的方法
实际使用的就是getEntryUsingComparator,基于comparator的二叉树遍历
通过你这里实现的compare来查找是否有与之对应的类
通过上面的信息,了解到最后一步其实找treeSet放置的元素的hashcode
回到HashMap的hashcode这里
HashMap的hashcode实现比较绕
hashcode = sum(entry.hashcode)//所有的entry的hashcode的和
entry.hashcode= key.hashcode^value.hashcode//key的hashcode和value的hashcode 异或操作
这里发现hashcode的值一定不会有问题,那么比较大小一定不会有问题
那为什么contains会找不到元素呢,其实因为因为楼主对treemap(TreeSet底层、红黑树)的结构不了解,遍历的时候因为值的大小问题遍历导致,这里不详细说明红黑树了,可以自行查看
其实本质是因为 hashcode可以为负数,那么大小的判断就会有误,从而二叉树那里除了问题。修改一下代码即可class HashCompare implements Comparator<Map>{ @Override public int compare(Map o1, Map o2) { int h1 = o1.hashCode(); int h2 = o2.hashCode(); if(h1>h2){ return 1; }else if(h1<h2){ return -1; } return 0; } }
2014年9月18日 14:12
-
按照楼主自定义的comparetor对比,画出来的树是: m1 m2 m3 m4 m5 m6 m8 m7 可以看出是一个排序二叉树 其定义很简单:(1)非叶子节点至少一边的分支非NULL;(2)叶子节点左右分支都为NULL;(3)每一个节点记录一个数据,同时左分支的数据都小于右分支的数据。 对于这个问题: 数据只得是hashcode。 那么 contain是如何查找的呢?其实是:m7 ==> m4 ==》M5 结论: 1、一直m3的hashcode(m3: 2076073718),从二叉树结叶子结点 按照 自定义的 HashCompare 去查找, 分别按照 减法对比hashcode, 最后找错了,路径,返回null,boolean是false。 2、HashCompare 非常重要,参与构造树,以及查找树。 一下是java源代码跟踪部分: m1: 117608867 m2: 75431906 m3: 2076073718 m4: -1655436036 m5: -1981877973 m6: -1086123974 m7: -952394827 m8: -1639907518 Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } 调用包含的时候: 你可以在TreeSet中加一个断点看看,此处的m是TreeMap,所以 public boolean contains(Object o) { return m.containsKey(o); } 调用treeMap中的containsKey方法 public boolean containsKey(Object key) { return getEntry(key) != null; } 相应的getEntry方法。 final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; } 因为:getEntry()方法中:comparator 不为null,此处为 自定义的 HashCompare if (comparator != null) return getEntryUsingComparator(key); 所以它又调用了 getEntryUsingComparator 方法,注意 此处的key其实是m3, 该方法里面的comparator还是HashCompare final Entry<K,V> getEntryUsingComparator(Object key) { K k = (K) key; Comparator<? super K> cpr = comparator; if (cpr != null) { Entry<K,V> p = root; while (p != null) { int cmp = cpr.compare(k, p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } } return null; }
2014年9月19日 11:57
相关推荐
TreeSet 的其他方法,如 contains、remove、size 等,也都是调用 TreeMap 的对应方法来实现。 红黑树数据结构是 TreeSet 的核心,它是一种自平衡的排序二叉树。红黑树的每个节点都有一个颜色,要么是红色,要么是...
3. **基本操作**:`add()`用于向`TreeSet`中添加元素,`remove()`用于删除指定元素,`contains()`用于检查集合是否包含某个元素。`clear()`则可以清空整个集合。 4. **迭代器**:`TreeSet`遵循Java集合框架的迭代...
使用`TreeSet`的`contains()`方法查找特定书籍是否已被借出,如果在持卡人的`TreeSet`中找到,就表示已被借出。遍历持卡人集合,找出借阅过这本书的所有记录。 5. **查询借书卡的借出记录** 遍历持卡人`TreeSet`...
比较遗憾的是,TreeSet 虽然实现起来也比较简单,但它有着和 HashSet 一样的问题,会自动排序 5:LinkedHashSet去重(有序) 从代码和执行结果可以看出,LinkedHashSet 是到目前为止,实现比较简单,且最终生成的新...
6. containsValue()方法:containsValue()方法判断Map中是否包含指定的值。 7. get()方法:get()方法返回指定键对应的值。 8. putAll()方法:putAll()方法将另一个Map中的键值对添加到当前Map中。 四、AVL树在Map中...
Set接口本身不提供任何实现细节,具体实现需要借助其子类,如HashSet和TreeSet等。在使用Set接口时,开发者常常遇到的问题包括如何添加、删除和遍历元素等。下面是对这些问题的详细分析和解决方案。 首先,向Set中...
它有多种实现类,如HashSet和TreeSet,每个类都有其特定的特性和用途。 1. **HashSet** - **构造函数**:HashSet提供了多种构造方法,包括无参构造、接受Collection参数的构造以及指定初始容量和加载因子的构造。...
TreeSet<String> treeSet = new TreeSet(); treeSet.add("10"); // ... System.out.println("first_treeSet = " + treeSet.first()); System.out.println("last_treeSet = " + treeSet.last()); // ... } } ...
- `contains()`:需要遍历整个ArrayList,时间复杂度为O(N)。 2. HashMap: - HashMap利用数组和链表(或红黑树)的数据结构,提供快速的增删查改操作,其时间复杂度通常为O(1)。 - `containsKey()`:直接通过...
5. **操作与特性**:无论是`TreeSet`还是`TreeMap`,它们都提供了丰富的API,如`containsKey/containsValue`用于检查元素是否存在,`put/get/remove`用于添加、获取和移除元素,以及`firstKey/lastKey`用于获取最小...
- `contains(Object o)`:判断集合是否包含指定元素,通过调用HashMap的`containsKey()`方法实现。 4. 删除元素: - `remove(Object o)`:删除指定元素,调用HashMap的`remove()`方法,返回值表示操作是否成功。 ...
Collection 是 List 和 Set 的父接口,在 Collection 中定义了一些主要方法,例如 add、addAll、clear、contains、containsAll、equals、hashCode、isEmpty、iterator、remove、removeAll 和 retainAll 等。...
在Java中,Set接口有多个实现类,如HashSet、TreeSet等,它们各有各的特性。 首先,我们来聊聊HashSet。HashSet是最常用的Set实现类,它基于哈希表实现,因此插入和查找的平均时间复杂度为O(1)。然而,由于其内部...
console.log("Contains k "+sets.contains("k")); for(var c in sets.toArray()) console.log(sets.get(c)); var list=new Collection.SortedList(); list.compare=function(a,b) { if(a.name<b>b.name) return
Java集合体系是Java编程中非常核心的部分,涵盖了用于存储和操作数据的各种数据结构。在Java中,集合主要分为三大接口:List、...在面试中,深入理解集合的底层原理和操作性能,能展现出扎实的Java基础和问题解决能力。
HashSet是基于HashMap实现的,提供了常数时间的性能特点,即add, remove, contains操作的时间复杂度都是O(1)。它通过元素的哈希码来确定元素在内部的存储位置,因此不支持元素的有序性。由于内部使用HashMap来存储...
对于选项A的`toString()`,它不会影响`contains()`方法的结果,因为`toString()`主要用于提供对象的字符串表示形式,而`contains()`并不依赖于对象的字符串表示。 选项B的`equals()`方法则至关重要,因为它直接决定...
Java集合框架的并发集合类,如ConcurrentHashMap和CopyOnWriteArrayList等,是为了解决在多线程环境中使用集合时可能遇到的线程安全问题,提供了各自不同的线程安全实现方式。 在实际开发中,开发者需要根据具体...
Set接口的通用操作包括添加元素(`add()`)、删除元素(`remove()`)、检查元素是否存在(`contains()`)以及获取集合大小(`size()`)等。由于Set接口不保证元素的顺序,因此不适合那些依赖于元素特定顺序的应用场景。 在...
- `contains()`方法检查集合是否包含特定元素,如`set.contains("element");` - `isEmpty()`检查集合是否为空。 6. **遍历元素** - 使用`iterator()`获取迭代器,然后通过迭代器逐个访问元素,例如: ```java ...