Set集合
-确定性:对任意对象都能判定其是否属于某一个集合
-互异性:集合内每个元素都是无差异的,注意是内容差异
-无序性:集合内的顺序无关
Java中的集合接口Set
-HashSet (基于散列函数的集合,无序,不支持同步)
-TreeSet (基于树结构的集合,可排序的,不支持同步)
-LinkedHashSet(基于散列函数和双向链表的集合,可排序的,不支持同步)
HashSet
-基于HashMap实现的,可以容纳null元素,不支持同步
-add添加一个元素
-clear清除整个HashSet
-contains判定是否包含一个元素
-remove删除一个元素
-size大小
-retainAll计算两个集合交集
创建
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))
{
hs.add(6);
}
System.out.println(hs.size()); //7
hs.remove(4);
System.out.println(hs.size()); //6
hs.clear();
System.out.println(hs.size()); //0
集合交集
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);
//set1的元素不在set2里面的全部被删除,那么set1只剩一个元素c
System.out.println("交集是 "+set1); //输出c
遍历方法
创建Set
HashSet<Integer> hs2 = new HashSet<Integer>();
for(int i=0;i<100000;i++)
{
hs2.add(i);
}
traverseByIterator(hs2); //迭代器遍历,如下
traverseByFor(hs2); //for循环遍历,如下
}
迭代器遍历
public static void traverseByIterator(HashSet<Integer> hs)
{
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext())
{
iter1.next();
}
}
for循环遍历
public static void traverseByFor(HashSet<Integer> hs)
{
for(Integer item : hs)
{
; //任意语句
}
}
}
for循环速度比迭代器遍历快
LinkedHashSet
-继承HashSet,也是基于HashMap实现的,可以容纳null元素
-不支持同步
-方法和HashSet基本一致
add, clear, contains, remove, size
-通过一个双向链表维护插入顺序
创建
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
遍历方法
创建LinkedHashSet
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)
{
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext())
{
iter1.next();
}
}
for循环遍历
public static void traverseByFor(LinkedHashSet<Integer> hs)
{
for(Integer item : hs)
{
; //任意语句
}
}
LinkedHashSet是保留顺序的,其遍历顺序额插入顺序一致,而HashSet没有保留顺序,其遍历顺序无序
TreeSet
-基于TreeMap实现的,不可以容纳null元素,不支持同步
-add添加一个元素
-clear清除整个TreeSet
-contains判定是否包含一个元素
-remove删除一个元素
-size大小
-根据compareTo方法或指定Comparator排序
创建
import java.util.Iterator;
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
遍历方法
==TreeSet是按照所存储对象大小升序输出的 ==
创建TreeSet
TreeSet<Integer> ts2 = new TreeSet<Integer>();
for(int i=0;i<100000;i++)
{
ts2.add(i);
}
traverseByIterator(ts2); //迭代器遍历
traverseByFor(ts2); //for循环遍历
}
迭代器遍历
public static void traverseByIterator(TreeSet<Integer> hs)
{
Iterator<Integer> iter1 = hs.iterator();
while(iter1.hasNext())
{
iter1.next();
}
for循环遍历
public static void traverseByFor(TreeSet<Integer> hs)
{
for(Integer item : hs)
{
; //任意语句
}
}
}
判定等价
-HashSet, LinkedHashSet, TreeSet的元素都只能是对象
-HashSet和LinkedHashSet判定元素重复的原则
-判定两个元素的hashCode返回值是否相同,若不同,返回false
-若两者hashCode相同,判定equals方法,若不同,返回false;否则返回true
- hashCode和equals方法是所有类都有的,因为Object类有
-TreeSet判定元素重复的原则
-需要元素继承自Comparable接口
-比较两个元素的compareTo方法
HashSet, LinkedHashSet的例子
创建一个猫的类,只有一个成员变量size
class Cat
{
private int size;
public Cat(int size)
{
this.size = size;
}
}
创建一个HashSet和LinkedHashSet,里面的成员是Cat
import java.util.HashSet;
public class JudgeRuleTest {
public static void main(String[] args) {
HashSet<Cat> hs = new HashSet<Cat>();
hs.add(new Cat(1));
hs.add(new Cat(2));
hs.add(new Cat(3));
hs.add(new Cat(3));
System.out.println(hs.size()); //4
//最后的两只Cat(3),被判定不是相同的变量
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
//最后的两只Cat(4),被判定不是相同的变量
}
}
Cat类本身没有hashCode(),而是继承Object类的,而Object的hashCode()会返回对象信息和内存地址经过运算后的一个int值。两个不同的Cat(4)对象,他们的hashCode()返回值是不同的
创建狗的类,成员属性size,重写了hashCode(),equals(),toString()函数
class Dog {
private int size;
public Dog(int s) { ///构造函数
size = s;
}
public int getSize() {
return size;
}
public boolean equals(Object obj2) { //重写Dog自己的equals()函数
if(0==size - ((Dog) obj2).getSize()) {
return true;
} else {
return false;
}
}
public int hashCode() { //重写Dog自己的hashCode()函数
return size;
}
public String toString() {
return size + "";
}
}
创建一个HashSet和LinkedHashSet,里面的成员是Dog
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
//最后的两只Dog(4),被判定是相同的变量
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
//最后的两只Dog(4),被判定是相同的变量
Dog类本身改写了hashCode()方法,其返回值是具体的size,所以两个不同Dog(4),他们的hashCode()返回值是相同的
若两者hashCode相同,判定equals方法,若不同,返回false;否则返回true
重写时hashCode,equals,toString最好同时修改
创建Tiger类,包含成员变量size,实现Comparable接口
public class Tiger implements Comparable{
private int size;
public Tiger(int s) {
size = s;
}
public int getSize() {
return size;
}
public int compareTo(Object o) {
return size - ((Tiger) o).getSize();
}
}
Tiger实现Comparable接口,所以必须实现compareTo方法来比较大小。compareTo方法具体规则如下:
int a =obj1. compareTo (obj2);
如果a>0,则obj1>obj2;
如果a= =0;则obj1=obj2;
如果a<0,则obj1<obj2
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
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
}
因为HashSet, LinkedHashSet判断对象是否相同,不根据compareTo
TreeSet的例子
添加到TreeSet的,需要实现Comparable接口,即实现compareTo方法
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(4)是否相同,会调用compareTo方法,return size - ((Tiger) o).getSize();
表明两个size一样返回0,说明他们是相同的