标签:app apple 常用 prim == 优化 使用 元素 ati
set接口是一个无序的、唯一的容器(排列顺序与添加的顺序无关)
set接口提供的方法
public static void main(String[] args) {
/**
* 增:add/addAll
* 删:clear/remove/removeAll/retainAll
* 改:
* 查:contains/containsAll
* 遍历:iterator
* 其他:size/isEmpty
*/
Set<Integer> set = new HashSet<Integer>();
// [1]添加
// 无序
set.add(10);
set.add(3);
set.add(20);
set.add(0);
// 不能添加重复元素
boolean r = set.add(1);
System.out.println(set);
// 【2】删除
// set.remove(1);
// set.clear();
// System.out.println(set);
// 【3】查看是否包含
System.out.println(set.contains(1));
// 【4】其他
System.out.println(set.size());
System.out.println(set.isEmpty());
}
set接口的遍历方法
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("banana");
set.add("apple");
set.add("coco");
// 快速遍历
for (String item : set) {
System.out.println(item);
}
// 迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String item = it.next();
System.out.println(item);
}
}
set接口的实现类常用的有HashSet、LinkHashSet、TreeSet
HashSet是Set接口的实现类,底层数据结构是哈希表。
HashSet是线程不安全的(不保证同步)

根据哈希表的工作原理,请存储一个自定义对象到HashSet中。
public class Student {
private String id;
private String name;
private int age;
// …
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((id == null) ? 0 : id.hashCode());
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;
Student other = (Student) obj;
if (age != other.age)
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
总结
[1]如果向HashSet中存储元素时,元素一定要实现hashCode方法和equals方法。
[2] 优点:添加、删除、查询效率高;缺点:无序
LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表
哈希表用于散列元素;链表用于维持添加顺序。
如果要添加自定义对象元素,也需要重写hashCode和equals方法。
TreeSet 是Set接口的实现类,底层数据结构是二叉树。
TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。

添加一个新元素t的存储的步骤
[1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;
[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤
[3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤
输出时按照一定的规则:左子树->根节点->右子树
根据TreeSet的工作原理,向TreeSet添加自定义元素?
向TreeSet中添加元素时,一定要提供比较策略,否则会出现ClassCastException。
比较策略分两种:内部比较器和外部比较器
当一个自定义对象实现Comparable并实现compareTo方法时,通过指定具体的比较策略,此时称为内部比较器。
public class Student implements Comparable<Student>{
private String id;
private String name;
private int age;
// 。。。
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
if(this.getAge()<o.getAge()) {
return -1;
}else if(this.getAge() == o.getAge()) {
return 0;
}else {
return 1;
}
}
}
比较策略的几种情况
[1] 比较策略一般当前对象写在前面,待比较对象也在后面,比较结果默认升序,
如果想要降序,改变两个比较对象的位置即可。
return this.getAge() - o.getAge() ;
当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。
Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。
TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator
接口。
需求:按照字符串的长度比较
public class Test01 {
public static void main(String[] args) {
LenComparator lenComparator = new LenComparator();
TreeSet<String> set2 = new TreeSet<String>(lenComparator);
set2.add("banana");
set2.add("coco");
set2.add("apple");
set2.add("apple");
System.out.println(set2);
}
}
class LenComparator implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}
使用匿名内部类优化
public class Test02 {
public static void main(String[] args) {
TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
set2.add("banana");
set2.add("coco");
set2.add("apple");
set2.add("apple");
System.out.println(set2);
}
}
标签:app apple 常用 prim == 优化 使用 元素 ati
原文地址:https://www.cnblogs.com/w312308542/p/10817202.html