------- android培训、java培训、期待与您交流! ----------
Set集合
Set特点: 无顺序, 不可重复, 便利方式只有用Iterator
HashSet
HashSet
1. HashSet底层是由哈希表支持的,hashSet里面的元素都是唯一的, 如果一个与已经存在集合的元素相等的元素师不会被添加到集合中的, 方法参照jdk-api
2. 保证元素唯一性
1) 如果两个对象的equals结果为true, hashCode值不相等, 这两个元素不是相等的
2) 如果两个对象的eqauls结果为false, hashCode值相等, 这两个元素不是相等的
3) 如果两个对象的equals结果为true, hashCode值相等, 这两个元素师相等的
注意: 当元素插入Set中时如果hashCode与之前元素不相等, 那么直接插入集合, 不会判断equals结果
3. 如何重写hashCode
重写hashCode的方式有多种, 只要指定一个固定的值即可, 但是由于不同类型的对象可能会有相同的hashcode, 所以建议用以下的方法减小重复的概率
将quals方法中比较的属性的hashCode() 加上另一个其它属性的hashCode乘上一个质数, 如果属性类型是基本数据类型, 可以用包装类获取的hashCode进行计算
例如: int I = 31; return new Integer(id).hashCode() + name.hashCode() * I;
示例代码:
import java.util.*;
class HashSetTest {
public static void main(String[] args) {
// 创建一个HashSeet对, <>里面的内容可以忽略
HashSet<Student> set = new HashSet<Student>();
// 向set添加两个内容不同的对象
set.add(new Student("张三", 15));
set.add(new Student("李四", 15));
// 迭代输出
System.out.println("将两个内容不同的对象添加到set: ");
for (Iterator<Student> iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
// 再添加一个内容为"张三", 15的Student对象
set.add(new Student("张三", 15));
// 迭代输出
System.out.println("将与之前存在的对象内容一样的新对象添加到集合set: ");
for (Iterator<Student> iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
//定义一个Student对象
class Student {
//Student有两个属性, 姓名和年龄
String name;
int age;
//构造方法
Student(String name, int age) {
this.name = name;
this.age = age;
}
//重写equals方法
public boolean equals(Object obj) {
//如果两个对象是同一个对象返回true
if (this == obj) {
return true;
}
//如果两个对象时同一个字节码文件, 那么将obj强转为Student
if (this.getClass() == obj.getClass()) {
Student s = (Student)obj;
//根据姓名和年龄两个属性比较
boolean b = this.name.equals(s.name) && this.age == s.age;
return b;
}
return false;
}
//重写hashCode()
public int hashCode() {
return this.name.hashCode() + new Integer(this.age).hashCode() * 31;
}
//重写toString方法
public String toString() {
StringBuilder s = new StringBuilder();
s.append("姓名: " + this.name);
s.append("\t年龄: " + this.age);
return s.toString();
}
}
LinkedHashSet
1. LinkedHashSet继承自HashSet
2. 特点
取出元素的顺序与装入的顺序一致, 可以理解为不重复, 有序
代码示例:
import java.util.*;
class LinkedHashSetTest {
public static void main(String[] args) {
// 创建一个LinkedHashSet对象
LinkedHashSet list = new LinkedHashSet();
// 添加元素
list.add("hello");
list.add("world");
list.add(123);
list.add(true);
// 迭代输出
for (Iterator iter = list.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
TreeSet
1. 特点
集合中的元素有顺序, 不可重复, 这里的有顺序不是指添加与取出的顺序, 而是它会有一个升序的自然顺序, 也可以自定义排列顺序
TreeSet底层是二叉树实现的, 每次添加元素都要通过二叉树比较, 效率比HashSet低
2. 保证元素唯一性
1) 实现Comparable接口重写compareTo方法
此方法返回一个int型的整数, 可以将类内的一个属性进行比较, 如果小于0, 那么对象在字典顺序前面, 如果大于0, 在字典顺序后面, 等于0, 两个对象相等
2) 实现Comparator自定义比较器
必须重写Comparator接口中的compare()方法, 此方法实现的功能与上面的compateTo()一样
注意: 使用比较器在创建集合时, 将其作为参数传递TreeSet(Comparator c), jdk1.5和jdk1.6版本中第一次向TreeSet添加元素师不会进行比较,jdk1.7第一次添加元素也会执行比较
代码示例
import java.util.*;
class TreeSetTest {
public static void main(String[] args) {
// 创建一个TreeSet对象
TreeSet set1 = new TreeSet();
// 创建三个学生对象
Student s1 = new Student(2, "张三", 15);
Student s2 = new Student(3, "李四", 14);
Student s3 = new Student(1, "王五", 16);
set1.add(s1);
set1.add(s2);
set1.add(s3);
// id自然顺序
System.out.println("按id的自然顺序排列");
System.out.println("编号\t姓名\t年龄");
for (Iterator iter = set1.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
// 自定义比较器按年龄排序
TreeSet set2 = new TreeSet(new MyComparator());
// TreeSet set2 = new TreeSet();
set2.add(s1);
set2.add(s2);
set2.add(s3);
System.out.println("自定义比较器按年龄排列");
System.out.println("编号\t姓名\t年龄");
for (Iterator iter = set2.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
// 定义一个Student类实现Comparable接口
class Student implements Comparable {
// 三个属性
int id;
String name;
int age;
// 构造
Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
// 重写compareTo()
public int compareTo(Object obj) {
Student s = null;
// 将obj转换为当前对象类型
if (this.getClass() == obj.getClass()) {
s = (Student) obj;
}
// 按照id比较
if (this.id < s.id) {
return -1;
}
if (this.id > s.id) {
return 1;
}
return 0;
}
// toString()
public String toString() {
StringBuilder s = new StringBuilder();
s.append(this.id);
s.append("\t" + this.name);
s.append("\t" + this.age);
return s.toString();
}
}
// 自定义比较器
class MyComparator implements Comparator {
// 重写compare方法
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
// 按照age比较
if (s1.age < s2.age) {
return -1;
}
if (s1.age > s2.age) {
return 1;
}
return 0;
}
}
Set总结
HashSet 底层哈希表实现, 无序, 不重复, hashCode和equals确保唯一性, 线程不安全
|----- LinkedHashSet 继承自HashSet, 装入取出顺序一致, 线程不安全
TreeSet 底层是二叉树, 有序, 不重复, 线程不安全,TreeSet效率低, 自然顺序, 比较器确保唯一, 如果是compare结果为0, 那么是重复的
Set遍历集合代码
以HashSet为例
import java.util.*;
class SetLoop {
public static void main(String[] args) {
System.out.println("Set..............");
HashSet set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
System.out.println("只有这一种方式: iterator");
for (Iterator iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}