集合Set
- 确定性:对任何对象都能判定其是否属于某一个集合;
- 互异性:集合内每个元素都是不相同的,内容互异;
- 无序性:集合内的顺序无关;
Java中的集合接口Set
- HashSet(基于散列函数的集合,无序,不支持同步)
- TreeSet(基于树结构的集合,可排序的,不支持同步)
- LinkedHashSet(基于散列函数和双向链表的集合,可排序的,不支持同步)
HashSet
- 基于HashMap实现的,可以容纳null元素,不支持同步
- Set s=Collections.synchronizedSet(new HashSet(...));
- add 添加一个元素
- clear 清除整个HashSet
- contains 判定是否包含一个元素
- remove 删除一个元素
- size 大小
- retainsAll 计算两个集合交集
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
HashSet<Integer> hs = new HashSet<Integer>();
hs.add(null);
hs.add(1000);
hs.add(20);
hs.add(3);
hs.add(40000);
hs.add(5000000);
hs.add(3); //3 重复添加
hs.add(null); //null重复添加
System.out.println(hs.size()); //6
if(!hs.contains(6))//如果不包含6,则添加6
{
hs.add(6);
}
System.out.println(hs.size()); //7
hs.remove(4);
System.out.println(hs.size()); //7
//hs.clear();
//System.out.println(hs.size()); //0
System.out.println("============for循环遍历==============");
for(Integer item : hs)
{
System.out.println(item);
}
System.out.println("============测试集合交集==============");
HashSet<String> set1 = new HashSet<String>();
HashSet<String> set2 = new HashSet<String>();
set1.add("a");
set1.add("b");
set1.add("c");
set2.add("c");
set2.add("d");
set2.add("e");
//交集
set1.retainAll(set2);
System.out.println("交集是 "+set1);
System.out.println("============测试多种遍历方法速度==============");
HashSet<Integer> hs2 = new HashSet<Integer>();
for(int i=0;i<100000;i++) {
hs2.add(i);
}
traverseByIterator(hs2);
traverseByFor(hs2);
}
public static void traverseByIterator(HashSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============迭代器遍历==============");
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext()){
iter1.next();
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
public static void traverseByFor(HashSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============for-each遍历==============");
for(Integer item : hs)
{
;
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
}
测试结果
6
7
7
============for循环遍历==============
null
40000
3
20
6
1000
5000000
============测试集合交集==============
交集是 [c]
============测试多种遍历方法速度==============
============迭代器遍历==============
59033300纳秒
============for-each遍历==============
96651700纳秒
- 对集合进行元素重复添加无效
- 遍历的输出顺序与元素添加顺序无关
- 迭代器遍历效率更高
LinkedHashSet
- 继承HashSet,也是基于HashMap实现的,可以容纳null元素
- 不支持同步
- Set s = Collection.synchronizedSet(New LinkedHashSet(...));
- 方法和HashSet基本一致
- add,clear,contains,remove,size
- 通过一个双向链表维护插入顺序
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet<Integer> lhs = new LinkedHashSet<Integer>();
lhs.add(null);
lhs.add(1000);
lhs.add(20);
lhs.add(3);
lhs.add(40000);
lhs.add(5000000);
lhs.add(3); //3 重复
lhs.add(null); //null 重复
System.out.println(lhs.size()); //6
if(!lhs.contains(6))
{
lhs.add(6);
}
System.out.println(lhs.size()); //7
lhs.remove(4);
System.out.println(lhs.size()); //6
//lhs.clear();
//System.out.println(lhs.size()); //0
System.out.println("============for循环遍历==============");
for(Integer item : lhs)
{
System.out.println(item);
}
LinkedHashSet<Integer> lhs2 = new LinkedHashSet<Integer>();
for(int i=0;i<100000;i++)
{
lhs2.add(i);
}
traverseByIterator(lhs2);
traverseByFor(lhs2);
}
public static void traverseByIterator(LinkedHashSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============迭代器遍历==============");
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext()){
iter1.next();
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
public static void traverseByFor(LinkedHashSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============for-each遍历==============");
for(Integer item : hs)
{
;
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
}
测试结果
6
7
7
============for循环遍历==============
null
1000
20
3
40000
5000000
6
============迭代器遍历==============
12353400纳秒
============for-each遍历==============
9365600纳秒
- 遍历结果和插入顺序一致
- for-each遍历更快
TreeSet
- 基于TreeMap实现,不可以容纳null元素,不支持同步
- SortedSet s=Collections.synchronizedSortedSet(new TreeSet(...));//变成同步
- add 添加一个元素
- clear清除整个TreeSet
- contains判断是否包含一个元素
- remove删除一个元素
- size大小
- 根据compareTo方法或指定Comparator排序
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>();
// ts.add(null); 错误,不支持null
ts.add(1000);
ts.add(20);
ts.add(3);
ts.add(40000);
ts.add(5000000);
ts.add(3); //3 重复
System.out.println(ts.size()); //5
if(!ts.contains(6))
{
ts.add(6);
}
System.out.println(ts.size()); //6
ts.remove(4);
System.out.println(ts.size()); //5
//lhs.clear();
//System.out.println(lhs.size()); //0
System.out.println("============for循环遍历==============");
for(Integer item : ts)
{
System.out.println(item);
}
TreeSet<Integer> ts2 = new TreeSet<Integer>();
for(int i=0;i<100000;i++)
{
ts2.add(i);
}
traverseByIterator(ts2);
traverseByFor(ts2);
}
public static void traverseByIterator(TreeSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============迭代器遍历==============");
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext()){
iter1.next();
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
public static void traverseByFor(TreeSet<Integer> hs)
{
long startTime = System.nanoTime();
System.out.println("============for-each遍历==============");
for(Integer item : hs)
{
;
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(duration + "纳秒");
}
}
输出结果:
5
6
6
============for循环遍历==============
3
6
20
1000
40000
5000000
============迭代器遍历==============
8987700纳秒
============for-each遍历==============
6676000纳秒
TreeSet按照所存储对象大小升序输出的
元素重复的判定
- HashSet,LinkedHashSet,TreeSet的元素都只能是对象;
- HashSet和LinkedHashSet判定元素是否重复原则:
- 判定两个元素hashCode返回值是否相同,若不同,返回false;
- 若两者hashCode相同,判定equals方法,若不同,返回false;否则,返回true;
- hashCode和equals方法是所有类都有的,因为Object类有
- TreeSet判定元素重复的原则
- 需要元素继承自Comparable接口
- 比较两个元素的compareTo方法
HashSet和LinkedHashSet例程:
Cat.java
class Cat
{
private int size;
public Cat(int size)
{
this.size = size;
}
}
Dog.java
class Dog {
private int size;
public Dog(int s) {
size = s;
}
public int getSize() {
return size;
}
public boolean equals(Object obj2) {
System.out.println("Dog equals()~~~~~~~~~~~");
if(0==size - ((Dog) obj2).getSize()) {
return true;
} else {
return false;
}
}
public int hashCode() {
System.out.println("Dog hashCode()~~~~~~~~~~~");
return size;
}
public String toString() {
System.out.print("Dog toString()~~~~~~~~~~~");
return size + "";
}
}
Tiger.java
public class Tiger implements Comparable{
private int size;
public Tiger(int s) {
size = s;
}
public int getSize() {
return size;
}
public int compareTo(Object o) {
System.out.println("Tiger compareTo()~~~~~~~~~~~");
return size - ((Tiger) o).getSize();
}
}
ObjectHashSetTest
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class ObjectHashSetTest {
public static void main(String[] args) {
System.out.println("==========Cat HashSet ==============");
HashSet<Cat> hs = new HashSet<Cat>();
hs.add(new Cat(2));
hs.add(new Cat(1));
hs.add(new Cat(3));
hs.add(new Cat(5));
hs.add(new Cat(4));
hs.add(new Cat(4));
System.out.println(hs.size()); //6
System.out.println("========================");
LinkedHashSet<Cat> lhs= new LinkedHashSet<Cat>();
lhs.add(new Cat(2));
lhs.add(new Cat(1));
lhs.add(new Cat(3));
lhs.add(new Cat(5));
lhs.add(new Cat(4));
lhs.add(new Cat(4));
System.out.println(lhs.size()); //6
System.out.println("==========Dog HashSet ==============");
HashSet<Dog> hs2 = new HashSet<Dog>();
hs2.add(new Dog(2));
hs2.add(new Dog(1));
hs2.add(new Dog(3));
hs2.add(new Dog(5));
hs2.add(new Dog(4));
hs2.add(new Dog(4));
System.out.println(hs2.size()); //5
System.out.println("========================");
LinkedHashSet<Dog> lhs2= new LinkedHashSet<Dog>();
lhs2.add(new Dog(2));
lhs2.add(new Dog(1));
lhs2.add(new Dog(3));
lhs2.add(new Dog(5));
lhs2.add(new Dog(4));
lhs2.add(new Dog(4));
System.out.println(lhs2.size()); //5
System.out.println("==========Tiger HashSet ==============");
//HashSet的判定不关心CompareTo方法
HashSet<Tiger> hs3 = new HashSet<Tiger>();
hs3.add(new Tiger(2));
hs3.add(new Tiger(1));
hs3.add(new Tiger(3));
hs3.add(new Tiger(5));
hs3.add(new Tiger(4));
hs3.add(new Tiger(4));
System.out.println(hs3.size()); //6
System.out.println("========================");
LinkedHashSet<Tiger> lhs3= new LinkedHashSet<Tiger>();
lhs3.add(new Tiger(2));
lhs3.add(new Tiger(1));
lhs3.add(new Tiger(3));
lhs3.add(new Tiger(5));
lhs3.add(new Tiger(4));
lhs3.add(new Tiger(4));
System.out.println(lhs3.size()); //6
}
}
输出:
5
6
6
============for循环遍历==============
3
6
20
1000
40000
5000000
============迭代器遍历==============
8987700纳秒
============for-each遍历==============
6676000纳秒
PS C:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo> cd 'c:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo'; & 'C:\Users\zhang\.vscode\extensions\vscjava.vscode-java-debug-0.25.1\scripts\launcher.bat' 'C:\Program Files\Java\jdk-12.0.2\bin\java.exe' '-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=localhost:8842' '-Dfile.encoding=UTF-8' '-cp' 'C:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo\bin' 'HashSetJudgeRuleTest'
4
PS C:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo> cd 'c:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo'; & 'C:\Users\zhang\.vscode\extensions\vscjava.vscode-java-debug-0.25.1\scripts\launcher.bat' 'C:\Program Files\Java\jdk-12.0.2\bin\java.exe' '-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=localhost:8863' '-Dfile.encoding=UTF-8' '-cp' 'C:\Users\zhang\Documents\VS Code\Java\JavaCoreTechnique\SetDemo\bin' 'ObjectHashSetTest'
==========Cat HashSet ==============
6
========================
6
==========Dog HashSet ==============
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog equals()~~~~~~~~~~~
5
========================
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog hashCode()~~~~~~~~~~~
Dog equals()~~~~~~~~~~~
5
==========Tiger HashSet ==============
6
========================
6
这三个方法三位一体:
- equals()是相同的
- hashCode()是相同的
- toString()也应该是相同的
TreeSet例程
import java.util.TreeSet;
public class ObjectTreeSetTest {
public static void main(String[] args) {
/*
System.out.println("==========Cat TreeSet ==============");
TreeSet<Cat> ts = new TreeSet<Cat>();
ts.add(new Cat(2));
ts.add(new Cat(1));
ts.add(new Cat(3));
ts.add(new Cat(5));
ts.add(new Cat(4));
ts.add(new Cat(4));
System.out.println(ts.size()); //5
System.out.println("==========Dog TreeSet ==============");
TreeSet<Dog> ts2 = new TreeSet<Dog>();
ts2.add(new Dog(2));
ts2.add(new Dog(1));
ts2.add(new Dog(3));
ts2.add(new Dog(5));
ts2.add(new Dog(4));
ts2.add(new Dog(4));
System.out.println(ts2.size()); //5
*/
//添加到TreeSet的,需要实现Comparable接口,即实现compareTo方法
System.out.println("==========Tiger TreeSet ==============");
TreeSet<Tiger> ts3 = new TreeSet<Tiger>();
ts3.add(new Tiger(2));
ts3.add(new Tiger(1));
ts3.add(new Tiger(3));
ts3.add(new Tiger(5));
ts3.add(new Tiger(4));
ts3.add(new Tiger(4));
System.out.println(ts3.size()); //5
}
}
结果
==========Tiger TreeSet ==============
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
Tiger compareTo()~~~~~~~~~~~
5