Set集合在开发中也会经常用到,有用的没用的都整理了一下。今天你Set了么?
1.基本概念
Set:一个不包含重复元素的collection接口,元素无序、唯一。
2.主要实现类
(1)HashSet
HashSet:实现Set接口,由哈希表支持,它不保证set的迭代顺序,无序唯一,不是同步的。
/**
* 用户类
* @author magic
*
*/
public class User {
String name;
int age;
public User(String name, int age) {
super();
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;
}
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
//自动生成hashCode()和equalis()方法,保证元素唯一
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) 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 class Test_Set {
public static void main(String[] args) {
// 子类对象实例化接口
Set set = new HashSet();
// 添加元素
set.add("sermia");
set.add("nike");
set.add("vans");
// 通过输出可以看出,set集合是散列排序
System.out.println(set);// [nike, sermia, vans]
// 删除单个元素
set.remove("sermia");
System.out.println(set);// [nike, vans]
// 删全部元素
set.removeAll(set);
System.out.println(set);// []
// 移除此set中的所有元素
// set.clear();
Set<User> set2 = new HashSet<User>();
// 添加自定义对象
set2.add(new User("一一", 11));
set2.add(new User("二二", 22));
set2.add(new User("三三", 33));
set2.add(new User("三三", 33));
// 自定义对象没有重写User类的 hashCode()和equals(Object obj)
// 自定义都会被添加到集合
System.out.println(set2);
// [User [name=一一, age=11], User [name=三三, age=33], User [name=三三,age=33], User [name=二二, age=22]]
// 自定义对象需要重写了User类的 hashCode()和equals(Object obj)
// 保证元素的唯一
System.out.println(set2);
// [User [name=二二, age=22], User [name=三三, age=33], User [name=一一,age=11]]
}
}
注:HashSet底层数据结构是哈希表,哈希表底层依赖hashCode()和equals()方法。集合添加元素的时候先判断hashCode()是否相同,不相同元素添加到集合;相同则执行equals()方法,equals()返回false,元素添加集合,返回true元素不添加到集合。hashCode()和equals()共同保证了集合元素的唯一性。
(2)TreeSet
TreeSet:实现Set接口,使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator(比较器排序)进行排序,有序(按某种规则排序)唯一,不是同步的。有序(按某种规则排序)唯一,不是同步的
构造方法:
//构造一个新的空set,该set根据其元素的自然顺序进行排序
TreeSet()
// 构造一个包含指定collection元素的新TreeSet,它按照其元素的自然顺序进行排序
TreeSet(Collection<? extends E> c)
// 构造一个新的空TreeSet,它根据指定比较器进行排序
TreeSet(Comparator<? super E> comparator)
// 构造一个与指定有序set具有相同映射关系和相同排序的新TreeSet
TreeSet(SortedSet<E> s)
//自然排序
Set set = new TreeSet();
//添加元素
set.add("sermia");
set.add("nike");
set.add("vans");
set.add("anta");
// 通过输出可以看出,set集合按照某种规则进行了排序(首写字母)
System.out.println(set);// [anta, nike, sermia, vans]
//比较器排序
Set<User> set2 = new TreeSet<User>(new Comparator<User>() {
public int compare(User o1, User o2) {
//排序规则
//返回<0,则在元素左边,>0则在元素右边,=0不添加到集合
return o1.age-o2.age;
}
});
//添加自定义对象
set2.add(new User("一一", 11));
set2.add(new User("二二", 22));
set2.add(new User("三三", 33));
System.out.println(set2);
//输出看出按照了age大小进行了排序
// [User [name=一一, age=11], User [name=二二, age=22], User [name=三三,age=33]]
注:TreeSet底层数据结构是红黑树,通过自然排序、比较器排序对元素排序。自然排序需要元素类实现Comparable接口,重写compareTo方法,通过控制返回值指定排序规则,而某些常用Java类已经实现了该接口,例如String,Integer等set的输出就可以证明。比较器排序需要集合构造方法接收Comparator的实现类对象,重写compare方法,通过返回值指定排序规则,当返回值为0时,不添加到集合。
(3)LinkedHashSet
LinkedHashSet:具有可预知迭代顺序的Set接口的哈希表和链接列表实现,有序唯一,不是同步的。有序唯一,不是同步的。
Set set = new LinkedHashSet();
// 添加元素
set.add("sermia");
set.add("nike");
set.add("vans");
set.add("anta");
// 通过输出可以看出,LinkedHashSet集合是顺序输出
System.out.println(set);// [sermia, nike, vans, anta]
Set<User> set2 = new LinkedHashSet<User>();
set2.add(new User("一一", 11));
set2.add(new User("二二", 22));
set2.add(new User("三三", 33));
//输出顺序和添加顺序一致
System.out.println(set2);
// [User [name=一一, age=11], User [name=二二, age=22], User [name=三三,age=33]]
注:底层数据结构是链表和哈希表,链表保证元素有序,哈希表保证元素唯一。
注:更多方法查看API