您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
javase第三季学习笔记-集合框架Set接口
发布时间:2017-08-10 15:53:35编辑:雪饮阅读()
public interface Set<E>
extends Collection<E>
一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
元素数量的增长,排序会跟着发生变化,所以说不保证迭代顺序
代码示例:
入口程序:
package com.vince.set;
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
/*
HashSet实现类
不保证迭代顺序
底层使用HashMap实现(哈希表),默认容量16,加载因子7.5(即当数组容量占用75%时就需要进行扩充了)
HashMap先进行hashCode比较,然后才进行equals比较,所以如果要添加多个对象,并且不允许重复则需要在对象所在类中重写这两个方法,否则对于对象若有多个相同的(引用地址不同)也会存储于集合中的。
hashCode方法返回对象属性的hashCode值
自定义对象是否重复的判断条件是:先判断hashCode是否相等,如果hashCode不相等,那么一定不是同一个对象。否则判断equals是否相等
如果equals返回false,表示对象不是同一个。
*/
public static void hashset(){
Set<String> set=new HashSet<String>();
set.add("聆三清妙音");
set.add("也好如是我闻");
System.out.println("元素个数是:"+set.size());
//把集合转换为数组的两种方式
//如果是对象就转换成对象数组
//Object[] objs=set.toArray();
//new String[]{}这个代表一个空的字符串数组
String[] names=set.toArray(new String[]{});
for (String string : names) {
System.out.println(string);
}
//------------存储自定义对象-------------
Set<Person> person=new HashSet<Person>();
Person p1=new Person("雪饮大侠",25);
person.add(p1);
person.add(new Person("雪饮大侠",25));
System.out.println("一共有元素:"+person.size()+"个");
}
public static void main(String[] args) {
hashset();
}
}
用到的person对象所在类:
package com.vince.set;
public class Person {
private String name;
private int age;
public Person() {
super();
// TODO 自动生成的构造函数存根
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
System.out.println(name+"的hashCode值:"+result);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
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 + "]";
}
}
public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
代码示例:
主程序:
package com.vince.set;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo {
/*
TreeSet实现类
使用元素的自然顺序对元素进行排序
底层使用TreeMap实现(树型结构)
使用TreeSet对自定义对象添加集合时需要先将该自定义对象所在类泛型实现接口
Comparable或Comparator
如类声明中"Comparable<类名>"
并提供该类对象的排序方法的实现,因为TreeSet实现类是会对对象进行排序的,而自定义对象则不知道到底按什么程序逻辑进行排序,所以需要对象自身所在类有提供排序方法。
*/
public static void treeset(){
Set<String> set=new TreeSet<String>();
set.add("雪饮大侠");
set.add("柠檬不萌");
set.add("柠檬不萌");
System.out.println("元素的个数是:"+set.size());
String[] names=set.toArray(new String[]{});
for (String string : names) {
System.out.println(string);
}
System.out.println("--添加自定义对象--");
Set<Emp> emps=new TreeSet<Emp>();
Emp e1=new Emp("雪饮大侠",24);
Emp e2=new Emp("柠檬不萌",25);
emps.add(e1);
emps.add(e2);
emps.add(e1);
emps.add(new Emp("柠檬不萌",26));
//这里无论是引用地址的重复add,还是add的时候临时new一个新的对象作为参数,由于对象所属类中compareTo按照age排序,
//所以只要引用地址相同就只计算一个进入集合,或者两个对象就算引用地址不同,只要他们age相同,照样只算一个进入集合
//只有引用地址不同,且age也不同才可以都进入集合中。
System.out.println("元素个数是:"+emps.size());
}
public static void main(String[] args) {
treeset();
}
}
所用到的类Emp:
package com.vince.set;
public class Emp implements Comparable<Emp>{
private String name;
private int 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;
}
public Emp() {
super();
// TODO 自动生成的构造函数存根
}
public Emp(String name, int age) {
super();
this.name = name;
this.age = age;
}
//compareTo返回为0则表示两个对象相同,则不允许加入到集合中
public int compareTo(Emp o){
if(o==null){throw new NullPointerException("参数不能为空!");}
else if(this.age<o.age){return -1;}
else if(this.age>o.age){return 1;}
else{return 0;}
}
@Override
public String toString() {
return "Emp [name=" + name + ", age=" + age + "]";
}
}
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, Serializable
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)
代码示例:
主程序:
package com.vince.set;
import java.util.LinkedHashSet;
import java.util.Set;
public class SetDemo {
/*
LinkedHashSet实现类
使用哈希表+双向链表实现
排序按照集合插入的顺序
底层是使用LinkedHashMap实现
多个对象实例也没有自动对比其值是否相同,只对比了引用地址,所以要想对对象有用则同样要实现hashCode和equals方法
*/
public static void linkedhashset(){
Set<Student> set=new LinkedHashSet<Student>();
Student s1=new Student("雪饮大侠",18);
Student s2=new Student("杜敏捷女侠",18);
set.add(s1);
set.add(s2);
//如果对象中有toString方法则可以直接像下面这样输出
System.out.println(set);
}
public static void main(String[] args) {
linkedhashset();
}
}
Student类:
package com.vince.set;
public class Student {
private String name;
private int 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;
}
public Student() {
super();
// TODO 自动生成的构造函数存根
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
关键字词:javase,集合框架Set接口