集合(1)
•
集合 Set
–
确定性:对任意对象都能判定其是否属于某一个集合
–
互异性:集合内每个元素都是无差异的,
注意是内容差异
–
无序性:集合内的顺序无关
集合(2)
•
Java中的集合接口Set
–
HashSet (基于散列函数的集合,无序,不支持同步)
–
TreeSet (基于树结构的集合,可排序的,不支持同步)
–
LinkedHashSet(基于散列函数和双向链表的集合,可排序的,不
支持同步)
集合(3)
•
HashSet
–
基于HashMap实现的,可以容纳null元素, 不支持同步
•
Set s = Collections.synchronizedSet(new HashSet(...)); //转化为支持同步
–
add 添加一个元素
–
clear 清除整个HashSet
–
contains 判定是否包含一个元素
–
remove 删除一个元素
size 大小
–
retainAll 计算两个集合交集
–
查看HashSetTest.java了解其基本用法
HashSetTest.java
public class HashSetTest {
public static void main(String[] args) {
HashSet<Integer> s1 = new HashSet<>();
s1.add(null);
s1.add(3);
s1.add(10000);
s1.add(null);
s1.add(3);//add(obj)
System.out.println("s1的大小: " + s1.size());
if (!s1.contains(6)) {//contains(obj)
s1.add(6);
}
System.out.println("s1的大小: " + s1.size());
s1.remove(10000);//remove(obj)
for(Integer i:s1)
System.out.print(i+" ");
System.out.println();
s1.clear();//clear()
System.out.println("s1执行clear之后的大小: "+s1.size());
}
}
运行结果:
集合(4)
•
LinkedHashSet
–
继承HashSet,也是基于HashMap实现的,可以容纳null元素
–
不支持同步
•
Set s = Collections.synchronizedSet(new LinkedHashSet(...));
–
方法和HashSet基本一致
•
add, clear, contains, remove, size
–
通过一个双向链表维护插入顺序
–
查看LinkedHashSetTest.java了解其基本用法
LinkedHashSetTest.java
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet<Integer> lhs = new LinkedHashSet<>();
lhs.add(1);
lhs.add(null);
if (!lhs.contains(2))
lhs.add(2);
lhs.remove(1);
//lhs.clear(); //与HashSet类似的四个简单方法
LinkedHashSet<Integer> lhs2 = new LinkedHashSet<>();
for (int i = 0; i < 100000; i++) {
lhs2.add(i);
}
traverseByIterator(lhs2);
traverseByForEach(lhs2);
}
public static void traverseByIterator(LinkedHashSet<Integer> lhs) {
Iterator<Integer> iterator = lhs.iterator();
Long start = System.nanoTime();
while (iterator.hasNext()) {
iterator.next();
}
Long end = System.nanoTime();
System.out.println("Iterator遍历耗时 " + (end - start) + "纳秒");
}
public static void traverseByForEach(LinkedHashSet<Integer> lhs) {
Long start = System.nanoTime();
for (Integer i : lhs)
{
; //do nothing
}
Long end = System.nanoTime();
System.out.println("for-each遍历耗时 " + (end - start) + "纳秒");
}
}
运行结果:
运行结果分析:Iterator遍历和for-each循环遍历本质上时间差别不大
集合(5)
•
TreeSet
–
基于TreeMap实现的,
不可以容纳null元素,
不支持同步 //因为人家要排序,所以不支持null元素
•
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
–
add 添加一个元素
–
clear 清除整个TreeSet
–
contains 判定是否包含一个元素
–
remove 删除一个元素 size 大小
–
根据compareTo方法或指定Comparator排序
–
查看TreeSetTest.java了解其基本用法
TreeSetTest.java
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Integer>ts=new TreeSet<>();
ts.add(1);
ts.add(1000);
//ts.add(null);//编译通过,运行报错 java.lang.NullPointerException
if(!ts.contains(2))
ts.add(2);
TreeSet<Integer>treeSet=new TreeSet<>();
for(int i=0;i<100000;i++)
{
treeSet.add(i);
}
traverseByForEach(treeSet);
traverseByIterator(treeSet);
}
public static void traverseByIterator(TreeSet<Integer>ts) {
Iterator<Integer> iterator = ts.iterator();
Long start = System.nanoTime();
while (iterator.hasNext()) {
iterator.next();
}
Long end = System.nanoTime();
System.out.println("Iterator遍历耗时 " + (end - start) + "纳秒");
}
public static void traverseByForEach(TreeSet<Integer>ts) {
Long start = System.nanoTime();
for (Integer i : ts)
{
; //do nothing
}
Long end = System.nanoTime();
System.out.println("for-each遍历耗时 " + (end - start) + "纳秒");
}
}
运行结果:
运行结果分析:两种遍历方式对于TreeSet差不多,时间上面没有太大差别
集合(6)
•
HashSet, LinkedHashSet, TreeSet的元素都只能是对象
•
HashSet和LinkedHashSet判定元素重复的原则
–
判定两个元素的hashCode返回值是否相同,若不同,返回false
–
若两者hashCode相同,判定equals方法,若不同,返回false;否则
返回true。
–
hashCode和equals方法是所有类都有的,因为Object类有 //可以改写方法以比较,不然除了基本类型之外都是不同的
•
TreeSet判定元素重复的原则
–
需要元素继承自Comparable接口
–
比较两个元素的compareTo方法
–详情见Cat.java&Dog.java&Tiger.java&TestJudgeRule.java
public class Cat {//未实现Comparable接口,不能比较,因此不能放入TreeSet中
private int size;
public Cat(int size){
this.size=size;
}
}
class Dog implements Comparable {//测试TreeSet.因为TreeSet中的元素要比较就必须实现Comparable接口
private int size;
public Dog(int size){
this.size=size;
}
public int getSize(){
return size;
}
@Override
public int compareTo(Object o) {
return this.getSize()-((Dog)o).getSize();
}
}
class Tiger { //测试HashSet或者LinkedHashSet 重写hashCode()和equals()方法
private int size;
public Tiger(int size){
this.size=size;
}
public int getSize(){
return size;
}
public int hashCode(){
return size;
}
public boolean equals(Object obj){
return this.getSize()==((Tiger)obj).getSize();
}
}
TestJudgeRule.java
public class TestJudgeRule {
public static void main(String[] args) {
TreeSet<Dog> dogTreeSet=new TreeSet<>();
dogTreeSet.add(new Dog(1));
dogTreeSet.add(new Dog(2));
dogTreeSet.add(new Dog(2));
System.out.println(dogTreeSet.size());//输出2
HashSet<Cat>catHashSet=new HashSet<>();
catHashSet.add(new Cat(1));
catHashSet.add(new Cat(1));
catHashSet.add(new Cat(1));
System.out.println(catHashSet.size());//输出3
TreeSet<Cat>catTreeSet=new TreeSet<>();
// catTreeSet.add(new Cat(1)); //运行错误。
// 因为TreeSet不会自动调用hashCode和equals方法,因此放进去的对象必须是能比较的。Cat类没有实现Comparable接口,不能比较。
HashSet<Tiger>tigerHashSet=new HashSet<>();
tigerHashSet.add(new Tiger(1));
tigerHashSet.add(new Tiger(2));
tigerHashSet.add(new Tiger(4));
tigerHashSet.add(new Tiger(4));
System.out.println(tigerHashSet.size());//输出3
}
}