——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——
一、Set接口
1 、 Set 接口
public interface Set<E> extends Collection<E>
一 个 不 包 含 重 复 元 素 的 collection 。更 确 切 地 讲 , set 不 包 含 满 足 el.equaIs(e2) 的 元 素 。对 el 和 e2, 并 且 最 多 包 含 一 个 null 元 素 。 正 如 其 名 称 所 暗 示 的 , 此 接 口 模 仿 了 数 学
上 的set 抽 象 。
2、HashSet 接口
public class HashSet<E> extends AbstractSet<E> implements Cloneable, Serializable
类实现Set接口,由哈希表支持。它是无序的,不允许元素的重复,允许使用null 元素。初始容量为16,加载因子为0.75
HashSet是如何保证元素唯一性呢?
是通过元素的两个方法,hashCode 和 equals来完成
如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals
注意:对于判断元素是否存在,以及删除等操作,依赖来的方法是元素的hashcode和equals方法
代码演示:
package com.joe.list;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
/**
* HashSet实现类: 1、不保证迭代顺序 2、底层使用HashMap实现(哈希表)
* 3、自定义对象是否重复的判断条件是:先判断hashCode是否相等,如果hashCode不相等,那么一定不是同一个对象
* 如果hashCode相等,那么就需要equals方法进一步判断,如果equals返回true,表示对象是同一个
* 如果equals返回false,表示对象不是同一个
*/
public class SetDemo {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<String>();
hs.add("大家好");
hs.add("努力");
hs.add("学习");
hs.add("JAVA");
hs.add("ANDROID");
System.out.println("元素的个数是:" + hs.size());
Iterator<String> it = hs.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("-------------------------------------");
// ----------存储自定义对象--------------------
HashSet<Person> hs1 = new HashSet<Person>();
Person p1 = new Person("LISI1", 30);
Person p2 = new Person("LISI2", 29);
Person p3 = new Person("LISI3", 32);
Person p4 = new Person("LISHI4", 28);
hs1.add(p1);
hs1.add(p2);
hs1.add(p3);
hs1.add(p4);
System.out.println("一共有元素:" + hs1.size());
Iterator it1 = hs1.iterator();
while (it1.hasNext()) {
Person p = (Person) it1.next();
System.out.println(p);
}
}
}
class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
return name.hashCode() + age * 31;
}
@Override
public boolean equals(Object obj) {
if (this==obj)
return true;
if(obj!=null && obj.getClass() == Person.class){
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}
return false;
}
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 + "]";
}
}
3、TreeSet
public class TreeSet<E> extends AbstractSet<E> implements
Cloneable, Serializable
基于TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeSet保证元素唯一性的依据:compareTo方法 return 0
第一种排序方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖Comparable方法。这种方式也称为元素的自然顺序,或者叫默认顺序。
第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
当两种排序都存在时,以比较器为主。、
定义一个类,实现Comparator接口,覆盖compare方法
代码演示:
package com.joe.list;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
/**
* TreeSet实现类
* 1、使用元素的自然顺序对元素进行排序
* 2、底层使用TreeMap实现(树型结构)
* 3、在TreeSet集合中存储自定义对象时,该对象必须实现Comparable/Comparator接口
* 4、底层是自然排序,如果要按照存入的顺序输出,重写compareTo()方法,改为“return 1“,如果要倒序输出,重写compareTo()方法,改为“return -1”
*/
public class TreeSetDemo {
public static void main(String[] args) {
Set<String> ts = new TreeSet<String>();
ts.add("小明");
ts.add("小张");
ts.add("小曾");
ts.add("小琪");
System.out.println("元素的个数是:" + ts.size());
Iterator it = ts.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("----------添加自定义对象------------");
Set<Student> students = new TreeSet<Student>();
Student s1 = new Student("小明", 30);
Student s2 = new Student("小张", 29);
Student s3 = new Student("小曾", 32);
Student s4 = new Student("小琪", 28);
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(new Student("利亚", 29));
System.out.println("元素的个数是:" + students.size());
Iterator<Student> it1 = students.iterator();
while (it1.hasNext()) {
System.out.println(it1.next());
}
}
}
class Student implements Comparable {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
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 "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object obj) {
if (!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student) obj;
if (this.age > s.age) { //先比较年龄
return 1;
} else if (this.age < s.age) {
return this.name.compareTo(s.name); //如果年龄相同,在比较名字
}
return -1;
}
}
自定义比较器的代码演示:
package com.joe.list;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数
*
* @author joe
*
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyCompare());
ts.add(new Student2("lisi",23));
ts.add(new Student2("lisi1",22));
ts.add(new Student2("lisi2",24));
ts.add(new Student2("lisi3",21));
Iterator it = ts.iterator();
while(it.hasNext()){
Student2 stu = (Student2)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
//自定义比较器
class MyCompare implements Comparator{
public int compare(Object o1,Object o2){
Student2 s1 = (Student2)o1;
Student2 s2 = (Student2)o2;
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
//把int类型封装成Integer对象,调用compareTo方法
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
// if(s1.getAge()>s2.getAge())
// return 1;
// if(s1.getAge()==s2.getAge())
// return 0;
// return -1;
}
return num;
}
}
class Student2 implements Comparable {
private String name;
private int age;
public Student2(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student2() {
super();
}
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 "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object obj) {
if (!(obj instanceof Student2))
throw new RuntimeException("不是学生对象");
Student2 s = (Student2) obj;
if (this.age > s.age) { // 先比较年龄
return 1;
} else if (this.age < s.age) {
return this.name.compareTo(s.name); // 如果年龄相同,在比较名字
}
return -1;
}
}
练习:
package com.joe.list;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 练习:按照字符串长度排序
*
* @author joe
*
*/
public class TreeSetPractice {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new StrLenComparator());
ts.add("abc");
ts.add("abec");
ts.add("at");
ts.add("abcwrw");
Iterator it = ts.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
class StrLenComparator implements Comparator {
//重写compare方法
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if (num == 0)
return s1.compareTo(s2);
return num;
}
}
4、LinkedHashSet
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>,Cloneable,Serializable
具有可预知迭代顺序的set接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重 链接列表。此链接列表定义了迭代顺序,即按照将元素插入到set中的顺序(插入顺序)进行迭代。注意:插入顺序不受在set中重新插入的元素的影响。(如果在s.contains(e)返回true后立即调用s.add(e),则元素e会被重新插入到sets中。)
代码演示:
package com.joe.list;
import java.util.LinkedHashSet;
import java.util.Set;
/* LinkedHashSet实现类 1、使用哈希表+双向链表实现 2、会以插入的顺序输出 3、底层是使用LinkedHashMap实现
* 4、是HashSet的子类
*/
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<Student> set = new LinkedHashSet<Student>();
Student s1 = new Student("小明", 18);
Student s2 = new Student("小张", 19);
Student s3 = new Student("小红", 17);
set.add(s3);
set.add(s2);
set.add(s1);
set.add(new Student("小红", 17));
System.out.println(set);
}
}
class Student implements Comparable {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
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 "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object obj) {
if (!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student) obj;
if (this.age > s.age) { // 先比较年龄
return 1;
} else if (this.age < s.age) {
return this.name.compareTo(s.name); // 如果年龄相同,在比较名字
}
return -1;
}
}