Set 接口基本介绍
Set
接口是Collection
接口的一个子接口,其主要特点如下:
-
不允许重复元素:
Set
接口的实现类不会包含重复的元素。更正式地说,不包含任何一对使得e1.equals(e2)
成立的元素e1
和e2
,并且最多只能有一个null
元素。当尝试添加重复元素时,添加操作将被忽略。 -
无序性:
Set
接口取出元素的顺序和添加元素的顺序不一致(但是每次取出的顺序是固定的),即无法通过索引访问Set
中的元素。
Set
接口的常用实现类有HashSet
、TreeSet
和LinkedHashSet
。可以使用迭代器和增强 for 循环遍历元素,但是不能使用普通 for 循环(不能使用索引)。下面的代码以其实现类HashSet
演示Set
接口的特点。
public class TestSet() {
public static void main(String[] args) {
Set set = new HashSet();
set.add("Phoebe");
set.add("Monica");
set.add("Phoebe"); // 重复
set.add("Ross");
set.add("Chandler");
set.add("Rachel");
set.add(null);
set.add(null); // 再次添加 null
// 10 次输出结果均为:set=[Phoebe, null, Rachel, Ross, Chandler, Monica]
// 重复的 Phoebe 和 null 都只输出了一个,
// 取出顺序和添加顺序不一致但每次取出顺序都是相同的。
for (int i = 0; i < 10; i++) {
System.out.println("set=" + set);
}
}
}
注意:如果Set
集合的元素是可变对象时,必须要小心。如果以影响equals()
方法比较结果的方式修改Set
中的元素的值,集合的行为是未指定的。这种情况的特例是Set
不能将自身作为元素。以下以一个简单的 Person 类来测试修改HashSet
中元素的值使得两个元素equals()
方法比较结果相同时的情况。
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
public class TestModifyValue() {
public static void main(String[] args) {
Set set = new HashSet();
// 创建 3 个 Person 实例,其中 rose1.equals(rose2) 成立
Person jack = new Person("Jack");
Person rose1 = new Person("Rose");
Person rose2 = new Person("Rose");
// 将其添加到 set 中
set.add(jack);
set.add(rose1);
set.add(rose2);
// 可以看到只添加成功一个姓名为 Rose 的 Person 实例,其应为 rose1。
System.out.println("set = " + set); // set = [Person{name='Rose'}, Person{name='Jack'}]
// 将 set 添加到自身中,未添加成功
set.addAll(set);
System.out.println("set = " + set); // set = [Person{name='Rose'}, Person{name='Jack'}]
// 将 rose1 的 name 属性修改为 Jack
rose1.setName("Jack");
System.out.println(rose1.equals(jack)); // true
// 可以看到此时 set 集合中仍有两个对象,其 equals() 方法比较结果相同。
System.out.println("set = " + set); // set = [Person{name='Jack'}, Person{name='Jack'}]
}
}
Set 接口常用方法
Set
接口和List
接口一样,也是Collection
接口的子接口,因此常用方法和Collection
接口一样。但需要注意由于Set
接口不包含重复元素,所以addAll()
方法的参数也是Set
时,addAll
操作会有效地修改该集合,使其值为两个集合的并集。
public class SetAddAll() {
public static void main(String[] args) {
Set set = new HashSet();
set.add("Phoebe");
set.add("Monica");
set.add("Ross");
System.out.println("set = " + set); // set = [Phoebe, Ross, Monica]
Set set1 = new HashSet();
set1.add("Phoebe");
set.add("Chandler");
set.addAll(set1);
System.out.println("set = " + set); // set = [Phoebe, Ross, Chandler, Monica]
}
}
Set 接口遍历元素方式
Set
接口遍历元素的方式和Collection
接口的一样,可以使用迭代器和增强 for 循环来遍历元素,但不能通过索引的方式来遍历元素。
public class SetThroughElements() {
public static void main(String[] args) {
Set set = new HashSet();
set.add("Phoebe");
set.add("Monica");
set.add("John");
System.out.println("---使用迭代器---");
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj = " + obj);
}
System.out.println("---使用增强 for---");
for (Object o :set) {
System.out.println("o = " + o);
}
// 不能使用普通 for 循环,因为 Set 不支持索引
}
}
标签:常用,Set,name,接口,Person,add,set,public
From: https://www.cnblogs.com/echo97/p/17481557.html