java集合-TreeSet
来源:互联网 发布:yum下载 编辑:程序博客网 时间:2024/06/06 02:16
一:基本概念
TreeSet基于 TreeMap 的 NavigableSet 实现。
- 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
- 此实现为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。
- 如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 Comparable 或 Comparator。)这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是 定义良好的;它只是违背了 Set 接口的常规协定。
- TreeSet不是同步的。如果多个线程同时访问一个 TreeSet,而其中至少一个线程修改了该 set,那么它必须 外部同步。这一般是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用
Collections.synchronizedSortedSet
方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问:SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
- 此类的 iterator 方法返回的迭代器是快速失败 的:在创建迭代器之后,如果从结构上对 set 进行修改,除非通过迭代器自身的 remove 方法,否则在其他任何时间以任何方式进行修改都将导致迭代器抛出 ConcurrentModificationException。因此,对于并发的修改,迭代器很快就完全失败,而不会冒着在将来不确定的时间发生不确定行为的风险。
- 注迭代器的快速失败行为无法得到保证,一般来说,存在不同步的并发修改时,不可能作出任何肯定的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。
实现结构图如下:(来源互联网)
public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable
API 简单测试:
package com.csu.collection;import java.util.Iterator;import java.util.TreeSet;public class TreeSetTest { public static void main(String[] args) { // TODO Auto-generated method stub testTreeSetAPIs(); } public static void testTreeSetAPIs() { String val; TreeSet<String> tSet = new TreeSet<>(); tSet.add("aaa"); // Set中不允许重复元素,所以只会保存一个“aaa” tSet.add("aaa"); tSet.add("bbb"); tSet.add("eee"); tSet.add("ddd"); tSet.add("ccc"); System.out.println("TreeSet:"+tSet); // 打印TreeSet的实际大小 System.out.printf("size : %d\n", tSet.size()); // 导航方法 // floor(小于、等于) System.out.printf("floor bbb: %s\n", tSet.floor("bbb")); // lower(小于) System.out.printf("lower bbb: %s\n", tSet.lower("bbb")); // ceiling(大于、等于) System.out.printf("ceiling bbb: %s\n", tSet.ceiling("bbb")); System.out.printf("ceiling eee: %s\n", tSet.ceiling("eee")); // ceiling(大于) System.out.printf("higher bbb: %s\n", tSet.higher("bbb")); // subSet() System.out.printf("subSet(aaa, true, ccc, true): %s\n", tSet.subSet("aaa", true, "ccc", true)); System.out.printf("subSet(aaa, true, ccc, false): %s\n", tSet.subSet("aaa", true, "ccc", false)); System.out.printf("subSet(aaa, false, ccc, true): %s\n", tSet.subSet("aaa", false, "ccc", true)); System.out.printf("subSet(aaa, false, ccc, false): %s\n", tSet.subSet("aaa", false, "ccc", false)); // headSet() System.out.printf("headSet(ccc, true): %s\n", tSet.headSet("ccc", true)); System.out.printf("headSet(ccc, false): %s\n", tSet.headSet("ccc", false)); // tailSet() System.out.printf("tailSet(ccc, true): %s\n", tSet.tailSet("ccc", true)); System.out.printf("tailSet(ccc, false): %s\n", tSet.tailSet("ccc", false)); // 删除“ccc” tSet.remove("ccc"); // 将Set转换为数组 String[] arr = (String[])tSet.toArray(new String[0]); for (String str:arr) System.out.printf("for each : %s\n", str); // 打印TreeSet System.out.printf("TreeSet:%s\n", tSet); // 遍历TreeSet for(Iterator<String> iter = tSet.iterator(); iter.hasNext(); ) { System.out.printf("iter : %s\n", iter.next()); } // 删除并返回第一个元素 val = (String)tSet.pollFirst(); System.out.printf("pollFirst=%s, set=%s\n", val, tSet); // 删除并返回最后一个元素 val = (String)tSet.pollLast(); System.out.printf("pollLast=%s, set=%s\n", val, tSet); // 清空HashSet tSet.clear(); // 输出HashSet是否为空 System.out.printf("%s\n", tSet.isEmpty()?"set is empty":"set is not empty"); }}
运行结果:
TreeSet:[aaa, bbb, ccc, ddd, eee]size : 5floor bbb: bbblower bbb: aaaceiling bbb: bbbceiling eee: eeehigher bbb: cccsubSet(aaa, true, ccc, true): [aaa, bbb, ccc]subSet(aaa, true, ccc, false): [aaa, bbb]subSet(aaa, false, ccc, true): [bbb, ccc]subSet(aaa, false, ccc, false): [bbb]headSet(ccc, true): [aaa, bbb, ccc]headSet(ccc, false): [aaa, bbb]tailSet(ccc, true): [ccc, ddd, eee]tailSet(ccc, false): [ddd, eee]for each : aaafor each : bbbfor each : dddfor each : eeeTreeSet:[aaa, bbb, ddd, eee]iter : aaaiter : bbbiter : ddditer : eeepollFirst=aaa, set=[bbb, ddd, eee]pollLast=eee, set=[bbb, ddd]set is empty
二:源码分析
1:变量定义:
NavigableMap对象,后边的集合操作就是基于它来操作的。
private transient NavigableMap<E,Object> m;
2:构造函数
public TreeSet() { this(new TreeMap<E,Object>()); }
创建一个空集,我们可以看出这个集合采用TreeMap来构造,以集合的值为Treemap的Key,因此集合不能存储重复的数据,这个构造函数使得集合排序按照TreeMap的自然顺序。
public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); }
构造一个新的空 TreeSet,它根据指定比较器进行排序。也就是说,我们可以通过自己实现comparator接口来自定义排序。
public TreeSet(Collection<? extends E> c) { this(); addAll(c); }
构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。我们可以看出通过调用addAll()方法将这个数据插入到集合中。
public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); }
同样的道理,构造一个包含SortedSet的集合。
3:主要方法分析:
iterator():
public Iterator<E> iterator() { return m.navigableKeySet().iterator(); }
我们可以看出TreeSet的迭代器是通过 NavigableMap对象的中KeySet方法获取的。
contains():
public boolean contains(Object o) { return m.containsKey(o); }
调用的事map的containsKey()方法;
add();
public boolean add(E e) { return m.put(e, PRESENT)==null; }
也是直接调用map的方法。
addAll():
public boolean addAll(Collection<? extends E> c) { // Use linear-time version if applicable if (m.size()==0 && c.size() > 0 && c instanceof SortedSet && m instanceof TreeMap) { SortedSet<? extends E> set = (SortedSet<? extends E>) c; TreeMap<E,Object> map = (TreeMap<E, Object>) m; Comparator<?> cc = set.comparator(); Comparator<? super E> mc = map.comparator(); if (cc==mc || (cc != null && cc.equals(mc))) { //还是通过调用TreeMap的方法添加元素 map.addAllForTreeSet(set, PRESENT); return true; } } return super.addAll(c); }
将指定 collection 中的所有元素添加到此 set 中。
应用实例
通TreeSet实现全排列
测试端:
mport java.util.Iterator;import java.util.Set;import java.util.TreeSet;public class TreeSetTest1 { public static void main(String[] args) { // TODO Auto-generated method stub Set<String> set=new TreeSet<>(); char []arr={'a','c','c','d'}; permutations(set, arr, 0, arr.length); Iterator<String> iterator=set.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } } public static void swap(char[] arr,int x,int y) { char temp=arr[x]; arr[x]=arr[y]; arr[y]=temp; } public static void permutations(Set<String> set,char[] arr,int start,int end) { if(start==end-1) { set.add(new String(arr)); } for(int i=start;i<end;i++) { swap(arr, start, i); permutations(set, arr, start+1, end); swap(arr, start, i); } }}
运行结果:
accdacdcadcccacdcadcccadccdacdaccdcadaccdcacdcca
0 0
- java集合-TreeSet
- Java 集合框架-TreeSet
- JAVA 集合类 TREESET
- Java集合之TreeSet
- java集合之TreeSet
- java中的TreeSet集合
- java集合------TreeSet
- java 集合框架-TreeSet
- Java集合之TreeSet
- Java集合之TreeSet
- Java TreeSet 集合
- 集合TreeSet【java】
- 《java集合》--TreeMap、TreeSet
- Java TreeSet集合
- Java集合之TreeSet
- JAVA-TreeSet集合
- JAVA-TreeSet集合
- java 集合 TreeSet
- 数据库里有数据但是python取出来发现是空的
- Egret常用第三方类库
- Oracle并行基础二
- java常用算法之返回字符串中目标字符串的位置
- cocos2d坐标转换
- java集合-TreeSet
- cout << fixed,precision,ios_base
- Win7配置修改neighbor
- Oracle 查询转换初探
- 剑指offer 树的子结构
- TeamCity自动编译设置教程
- myeclipse如何导出javadoc
- <meta name="viewport" content="width=device-width, ...>
- Android必知必会--NinePatch图片制作