Set集合用于存储不重复的元素,且set集合为了满足不重复都特点,需要实现equals和hashCode方法。
Set提供的方法:
- 将元素添加进Set:boolean add(E e)
- 将元素从Set删除:boolean remove(Object e)
- 判断是否包含元素:boolean contains(Object e)
例:
public class Main {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
System.out.println(set.add("abc")); // true
System.out.println(set.add("xyz")); // true
System.out.println(set.add("xyz")); // false,添加失败,因为元素已存在
System.out.println(set.contains("xyz")); // true,元素存在
System.out.println(set.contains("XYZ")); // false,元素不存在
System.out.println(set.remove("hello")); // false,删除失败,因为元素不存在
System.out.println(set.size()); // 2,一共两个元素
}
}
常用的set集合:
-
HashSet:
特点:无序、内部实现了HashMap,可以看做是没有vlaue的HashMap
核心代码:public class HashSet<E> implements Set<E> { // 持有一个HashMap: private HashMap<E, Object> map = new HashMap<>(); // 放入HashMap的value: private static final Object PRESENT = new Object(); public boolean add(E e) { return map.put(e, PRESENT) == null; } public boolean contains(Object o) { return map.containsKey(o); } public boolean remove(Object o) { return map.remove(o) == PRESENT; } }
-
SortSet(接口):实现类:TreeSet
特点:有序、与TreeSet相似,同样需要实现Comparable接口,实现compare方法
例:
public class Main {
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("apple");
set.add("banana");
set.add("pear");
set.add("orange");
for (String s : set) {
System.out.println(s);
}
}
}
输出:
apple
banana
orange
pear
如果没有实现Comparable接口,那么创建TreeSet时必须传入一个Comparator对象。
练习:给出一组List,设置为set集合,且需不重复和有序。
package SetPro;
import java.util.*;
public class SetTest {
public static void main(String[] args) {
List<Message> received = new ArrayList<Message>();//创建ArrayList
Message message1 = new Message(1, "Hello!");
Message message2 =new Message(2, "发工资了吗?");
Message message3 = new Message(2, "发工资了吗?");
Message message4 = new Message(3, "去哪吃饭?");
Message message5 = new Message(3, "去哪吃饭?");
Message message6 = new Message(4, "Bye");
received.add(message1);
received.add(message2);
received.add(message3);
received.add(message4);
received.add(message5);
received.add(message6);
List<Message> list = new ArrayList<Message>();
List<Message> displayMessages = process(received);
for (Message message : displayMessages) {
System.out.println(message.text);
}
}
static List<Message> process(List<Message> received) {
// TODO: 按sequence去除重复消息
Set<Message> set = new TreeSet<Message>(new Comparator<Message>() {
public int compare(Message o1, Message o2) {
return o1.text.compareTo(o2.text);
}
});
Iterator<Message> setIterator = set.iterator(); //一个set集合的迭代器
for (int i = 0; i < received.size(); i++) {
boolean b = set.add(received.get(i));//在set集合中添加list元素,返回值为Boolean类型,添加成功返回true,否则false
if(b) {//判断是否成功
received.remove(i);//成功则在list集合中移除该元素,
if(setIterator.hasNext()) {//判断set集合中是否有值,有值则取出存入list集合
received.add(setIterator.next());//在list集合中添加set中的元素
}else {
continue;
}
}else {
continue;
}
}
return received;
}
}
class Message {
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + sequence;
result = prime * result + ((text == null) ? 0 : text.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;
Message other = (Message) obj;
if (sequence != other.sequence)
return false;
if (text == null) {
if (other.text != null)
return false;
} else if (!text.equals(other.text))
return false;
return true;
}
public final int sequence;
public final String text;
public Message(int sequence, String text) {
this.sequence = sequence;
this.text = text;
}
}
代码练习中出错,一直报java.lang.UnsupportedOperationException,并且是在remove中报错。
原因:之前list集合创建方法:
List<Message> received = List.of(
new Message(1, "Hello!"),
new Message(2, "发工资了吗?"),
new Message(2, "发工资了吗?"),
new Message(3, "去哪吃饭?"),
new Message(3, "去哪吃饭?"),
new Message(4, "Bye")
);
该方法返回的类型是ArrayList,该类型并不是java.util.ArrayList 而是 java.util.Arrays.ArrayList 是Arrays的内部类,该实现类AbstractList实现类,并没有实现removeAll方法,当调用removeAll时因为需要调用remove方法,但是java.util.Arrays.ArrayList中没有remove方法,会调用AbstractList的remove方法。
这就是使用简便方法创建list的弊端,想要使用需要实现其remove类。