Java集合:Set接口总结 http://my.oschina.net/eager/blog/718013
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法。
Set实现类:HashSet、LinkedHashSet、TreeSet
HashSet:通过散列表存信息,无序存储,元素必须定义hashCode();
LinkedHashSet:内部使用链表维护元素顺序,按顺序插入顺序排序,也必须定义hashCode();
TreeSet:通过树结构(和TreeMap一致,使用红黑树)存储元素,存储数据有序。
HashSet :
1、当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的hashCode 值, 然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
2、如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
3、HashSet 集合判断两个元素相等的标准:两个对象通过 equals() 方法比较相等,并且两个对象的hashCode() 方法返回值也相等。即:如果两个对象通过 equals() 方法返回 true,这两个对象的hashCode 值也应该相同。
重写 hashCode() 方法的基本原则:
1、在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。
2、当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。
3、对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
LinkedHashSet :
1、LinkedHashSet 是 HashSet 的子类。
2、LinkedHashSet 集合根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
3、LinkedHashSet 性能插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
4、LinkedHashSet 有序但不允许集合元素重复。
TreeSet:
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet 支持两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
排序:
1、TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,
然后将集合元素按升序排列。
2、如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
3、实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过
compareTo(Object obj)方法的返回值来比较大小。
注意:
向 TreeSet 中添加的应该是同一个类的对象,
当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与
compareTo(Object obj) 方法有一致的结果:即如果两个对象通过 equals() 方法比较返回 true,
则通过 compareTo(Object obj) 方法比较应返回 0。
自然排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
<span class="hljs-keyword">import</span> java.util.*; <span class="hljs-comment">/* TreeSet:可以对Set集合中的元素进行排序。 底层数据结构是二叉树。 保证元素唯一性的依据: compareTo方法return 0. TreeSet排序的第一种方式:让元素自身具备比较性。 元素需要实现Comparable接口,覆盖compareTo方法。 也种方式也成为元素的自然顺序,或者叫做默认顺序。 TreeSet的第二种排序方式。 当元素自身不具备比较性时,或者具备的比较性不是所需要的。 这时就需要让集合自身具备比较性。 在集合初始化时,就有了比较方式。 需求: 往TreeSet集合中存储自定义对象学生。 想按照学生的年龄进行排序。 记住,排序时,当主要条件相同时,一定判断一下次要条件。 */</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Treeset</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ Set ts = <span class="hljs-keyword">new</span> TreeSet(); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi02"</span>, <span class="hljs-number">22</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi007"</span>, <span class="hljs-number">20</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi09"</span>, <span class="hljs-number">19</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi08"</span>, <span class="hljs-number">19</span>)); <span class="hljs-comment">// ts.add(new Student("lisi007",20));</span> <span class="hljs-comment">// ts.add(new Student("lisi01",40));</span> Iterator it = ts.iterator(); <span class="hljs-keyword">while</span> (it.hasNext()) { Student stu = (Student) it.next(); System.out.println(stu.getName() + <span class="hljs-string">"..."</span> + stu.getAge()); } } } <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>// 该接口强制让学生具备比较性。 </span>{ <span class="hljs-keyword">private</span> String name; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age; Student(String name, <span class="hljs-keyword">int</span> age) { <span class="hljs-keyword">this</span>.name = name; <span class="hljs-keyword">this</span>.age = age; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(Object obj)</span> </span>{ <span class="hljs-comment">// return 0;</span> <span class="hljs-keyword">if</span> (!(obj <span class="hljs-keyword">instanceof</span> Student)) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"不是学生对象"</span>); Student s = (Student) obj; System.out.println(<span class="hljs-keyword">this</span>.name + <span class="hljs-string">"....compareto....."</span> + s.name); <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.age > s.age) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.age == s.age) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.name.compareTo(s.name); } <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>; } <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> name; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> age; } } |
定制排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
<span class="hljs-keyword">import</span> java.util.*; <span class="hljs-comment">/* 当元素自身不具备比较性,或者具备的比较性不是所需要的。 这时需要让容器自身具备比较性。 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。 当两种排序都存在时,以比较器为主。 定义一个类,实现Comparator接口,覆盖compare方法。 */</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>//该接口强制让学生具备比较性。 </span>{ <span class="hljs-keyword">private</span> String name; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age; Student(String name,<span class="hljs-keyword">int</span> age) { <span class="hljs-keyword">this</span>.name = name; <span class="hljs-keyword">this</span>.age = age; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(Object obj)</span> </span>{ <span class="hljs-comment">//return 0;</span> <span class="hljs-keyword">if</span>(!(obj <span class="hljs-keyword">instanceof</span> Student)) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"不是学生对象"</span>); Student s = (Student)obj; <span class="hljs-comment">//System.out.println(this.name+"....compareto....."+s.name);</span> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.age>s.age) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; <span class="hljs-keyword">if</span>(<span class="hljs-keyword">this</span>.age==s.age) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.name.compareTo(s.name); } <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>; } <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> name; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> age; } } <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TreeSetDemo2</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ Set ts = <span class="hljs-keyword">new</span> TreeSet(); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi02"</span>,<span class="hljs-number">22</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi02"</span>,<span class="hljs-number">21</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi007"</span>,<span class="hljs-number">20</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi09"</span>,<span class="hljs-number">19</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi06"</span>,<span class="hljs-number">18</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi06"</span>,<span class="hljs-number">18</span>)); ts.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">"lisi007"</span>,<span class="hljs-number">29</span>)); <span class="hljs-comment">//ts.add(new Student("lisi007",20));</span> <span class="hljs-comment">//ts.add(new Student("lisi01",40));</span> Iterator it = ts.iterator(); <span class="hljs-keyword">while</span>(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+<span class="hljs-string">"..."</span>+stu.getAge()); } } } <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCompare</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Object o1,Object o2)</span> </span>{ Student s1 = (Student)o1; Student s2 = (Student)o2; <span class="hljs-keyword">int</span> num = s1.getName().compareTo(s2.getName()); <span class="hljs-keyword">if</span>(num==<span class="hljs-number">0</span>) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Integer(s1.getAge()).compareTo(<span class="hljs-keyword">new</span> Integer(s2.getAge())); <span class="hljs-comment">/* if(s1.getAge()>s2.getAge()) return 1; if(s1.getAge()==s2.getAge()) return 0; return -1; */</span> } <span class="hljs-keyword">return</span> num; } } |
性能分析:可以参考《Thinking in java》,数据如下:
————- TreeSet ————-
size add contains iterate
10 1316 506 180
100 199 101 22
1000 250 174 19
10000 266 224 21
————- HashSet ————-
size add contains iterate
10 1717 325 242
100 59 16 43
1000 66 25 27
10000 66 28 25
———- LinkedHashSet ———-
size add contains iterate
10 516 151 72
100 127 40 29
1000 145 57 27
10000 125 53 25
可以看出HashSet性能基本总比TreeSet好 ,除非确定需要排序时,才该使用TreeSet。
该博客仅作为复习记录。
本文大多数参考:http://www.cnblogs.com/shellway/p/3709074.html