先看集合框架图:
Set有HashSet和TreeSet两种实现类。
先看Set:
特点:无序、无下标、元素不可重复
方法:全部继承自Collection中的方法
增、删、遍历、判断与collection一致
看代码:
package com.collections.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* set的使用
* 特点:(1)无序(2)不能重复
* @author 华子
*/
public class Demo01 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// 添加
set.add("小米");
set.add("苹果");
set.add("华为");
set.add("华为");
System.out.println(set.size());
System.out.println(set.toString());
// 删除
// set.remove("苹果");
// System.out.println("删除后:"+set.size());
// System.out.println(set.toString());
// 遍历
// 增强for
for (String s :set
) {
System.out.println(s);
}
System.out.println("------------------------");
// 迭代器
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
System.out.println("------------------------");
for (String s :set) {
System.out.println(s);
}
// 判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
和之间的集合使用方法类似。
HasSet【重点】
存储结构:哈希表(数组+链表+红黑树)
存储过程(重复依据)
- 根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,进行第二步
- 再执行equals方法,如果equals为true,则认为是重复,否则形成链表
特点
存储过程:
- 基于HashCode计算元素存放位置
- 利用31这个质数,减少散列冲突
- 31提高执行效率
31 * i = (i << 5) - i
转为移位操作
- 31提高执行效率
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
- 利用31这个质数,减少散列冲突
新建集合 HashSet<String> hashSet = new HashSet<String>();
添加元素 hashSet.add( );
删除元素 hashSet.remove( );
遍历操作
1. 增强for for( type type : hashSet)
2. 迭代器 Iterator<String> it = hashSet.iterator( );
判断 hashSet.contains( );
hashSet.isEmpty();
先看HashSet的使用:
package com.collections.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* @author 华子
*/
public class Demo02 {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
// 1.添加元素
hashSet.add("刘德华");
hashSet.add("郭富城");
hashSet.add("张学友");
hashSet.add("黎明");
System.out.println("元素个数为:"+hashSet.size());
System.out.println(hashSet.toString());
// 删除元素
// hashSet.remove("刘德华");
// System.out.println("删除后:"+hashSet.size());
// System.out.println(hashSet.toString());
// 遍历元素
// 增强for
for (String s :hashSet
) {
System.out.println(s);
}
System.out.println("------------------------");
// 迭代器
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
还是差不多。
再来看HashSet存储Person类:
package com.collections.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程:
* (1)根据hashCode值计算保存的位置,如果为空,直接保存,如果不为空,则进入第二步
* (2)执行equals,如果为true,则判断为重复,否则,形成链表
* @author 华子
*/
public class Demo03 {
public static void main(String[] args) {
HashSet<Person> hashSet = new HashSet<>();
Person p1 = new Person("刘德华",20);
Person p2 = new Person("郭富城",21);
Person p3 = new Person("张学友",22);
Person p4 = new Person("黎明",23);
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
hashSet.add(p4);
hashSet.add(new Person("刘德华",20));
System.out.println("元素个数为:"+hashSet.size());
System.out.println(hashSet.toString());
// 删除
// hashSet.remove(new Person("刘德华",20));
// System.out.println("元素个数为:"+hashSet.size());
// System.out.println(hashSet.toString());
// 遍历元素
// 增强for
for (Person p :hashSet
) {
System.out.println(p);
}
System.out.println("------------------------");
// 迭代器
Iterator<Person> iterator = hashSet.iterator();
while (iterator.hasNext()){
Person p = iterator.next();
System.out.println(p);
}
}
}
Person类:
package com.collections.set;
import java.util.Objects;
/**
* 人类
* @author 华子
* 实现Comparable接口
*/
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
// 重写了比较方法,先按姓名比,再按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.getAge() - o.getAge();
return n1==0?n2:n1;
}
}
由于存储方式是先看HashCode计算位置,那个位置不为空,才进行equal,
我们再Person类中重写hasCode和equal方法:
使得它的haCode的是通过name和age生成,且equal比较的是属性。
这样就可以实现相同属性无法添加了、可以通过属性相同进行删除
运行结果:
可见HashSet的存储方式。
TreeSet:
特点
- 基于排列顺序实现元素不重复
- 实现SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
存储结构:红黑树
创建集合 TreeSet<String> treeSet = new TreeSet<>()
添加元素 treeSet.add();
删除元素 treeSet.remove();
遍历 1. 增强for 2. 迭代器
判断 treeSet.contains();
补充:TreeSet集合的使用
Comparator 实现定制比较(比较器)
Comparable 可比较的
TreeSet的使用:
package com.collections.set;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* @author 华子
*
*/
public class Demo04 {
public static void main(String[] args) {
// 创建集合
TreeSet<String> treeSet = new TreeSet<>();
treeSet.add("xxx");
treeSet.add("yyy");
treeSet.add("zzz");
treeSet.add("xxx");
System.out.println("元素个数:"+treeSet.size());
System.out.println(treeSet.toString());
// 删除
// treeSet.remove("xxx");
// System.out.println("删除之后:"+treeSet.size());
// 遍历
// 增强for循环
for (String s:treeSet) {
System.out.println(s);
}
System.out.println("----------------------------");
// 使用迭代器
Iterator<String> iterator = treeSet.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
和其他集合方法使用类似。
TreeSet存储Person类:
因为TreeSet存储的元素对象的类型必须实现Comparable接口,指定排序规则,而Peron中的对象没有固定的属性方法,所以Person要实现Comparable接口并重写compareTo方法。
Person类:
package com.collections.set;
import java.util.Objects;
/**
* 人类
* @author 华子
* 实现Comparable接口
*/
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
// 重写了比较方法,先按姓名比,再按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.getAge() - o.getAge();
return n1==0?n2:n1;
}
}
这样就可以进行元素存储了(排序方式先比姓名,再比年龄):
package com.collections.set;
import java.util.TreeSet;
/**
* TreeSet存储Peron类
* 存储结构:红黑树
* 要求:元素必须实现Comparable接口,compareTo返回值为0,则确认为重复
* @author 华子
*/
public class Demo05 {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<>();
Person p1 = new Person("aaa",18);
Person p2 = new Person("bbb",19);
Person p3 = new Person("ccc",20);
Person p4 = new Person("ddd",21);
Person p5 = new Person("ddd",22);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
treeSet.add(p5);
System.out.println("元素个数:"+treeSet.size());
System.out.println(treeSet.toString());
}
}
运行结果:
还可以用Comparator 定制比较器(使用匿名内部类):
直接再匿名内部类里重写比较方法:
package com.collections.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @author 华子
* TreeSet的使用
* Comparator 定制比较(比较器) 使用匿名内部类
* Comparable,可比较的
*/
public class Demo06 {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int n1 = p1.getAge() - p2.getAge();
int n2 = p1.getName().compareTo(p2.getName());
return n1==0?n2:n1;
}
});
Person p1 = new Person("aaa",18);
Person p2 = new Person("bbb",19);
Person p3 = new Person("ccc",20);
Person p4 = new Person("ddd",21);
Person p5 = new Person("eee",21);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
treeSet.add(p4);
treeSet.add(p5);
System.out.println(treeSet.toString());
}
}
运行结果:
这样也可以添加元素。
TreeSet案例:
使用TreeSet实现字符串按长度排序:hello world zhangsan lisi wangwu xian najing
package com.collections.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet案例:使用TreeSet实现字符串按长度排序
* hello world zhangsan lisi wangwu xian najing
* @author 华子
*
*/
public class Demo07 {
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length()- o2.length();
int n2 = o1.compareTo(o2);
return n1==0?n2:n1;
}
});
treeSet.add("hello world");
treeSet.add("zhangsan");
treeSet.add("lisi");
treeSet.add("wangwu");
treeSet.add("xian");
treeSet.add("najing");
System.out.println(treeSet.toString());
}
}
运行结果: