【Java集合框架】3 - 11 TreeMap 集合
§3-11 TreeMap
集合
3-11.1 特点与底层原理
TreeMap
位于 java.util
包下,是 Map
的一个实现类,其中没有独特的方法,一般直接使用 Map
中的方法即可。
TreeMap
特点:
TreeMap
与TreeSet
一样,在底层采用红黑树存储数据;- 由键决定特点:可排序、无重复、无索引;
- 可排序:指的是对键进行排序;
- 默认对键升序排序,也可自定义排序规则;
比较规则:同 TreeSet
中的自定义比较规则方法
- 默认使用:Java Bean 类实现
Comparable
接口并重写compareTo
方法; - 覆盖使用:往构造器中传入
Comparator
接口的实现类对象,重写compare
方法(在默认方式不能满足需求时使用);
两种方式同时存在时,则会优先采用 Comparator
中的 compare
方法排序。
3-11.2 案例演示
需求一:键表示 ID,值表示商品名称。要求按照 ID 升序、降序排列商品。
TreeMap<Integer, String> goods = new TreeMap<>();
goods.put(0, "粤利粤");
goods.put(2, "康帅傅");
goods.put(1, "脉劫");
goods.put(3, "雷碧");
//默认升序
System.out.println(goods);
//键表示 ID,值表示商品名称。要求按照 ID 升序、降序排列商品
TreeMap<Integer, String> goods = new TreeMap<>((o1, o2) -> o2 - o1);
goods.put(0, "粤利粤");
goods.put(2, "康帅傅");
goods.put(1, "脉劫");
goods.put(3, "雷碧");
//降序
System.out.println(goods);
得到结果(降序):
{3=雷碧, 2=康帅傅, 1=脉劫, 0=粤利粤}
需求二:键表示学生对象,值表示籍贯。要求按照学生年龄升序排列,年龄相等则按姓名首字母排列,同名同年视为同一个人。
//Java Bean 类
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String toString() {
return name + "(" + age + ")";
}
@Override
public int compareTo(Student o) {
//要求按照学生年龄升序排列,年龄相等则按姓名首字母排列,同名同年视为同一个人
int i = this.getAge() - o.getAge();
i = i == 0 ? this.getName().compareTo(o.getName()) : i;
return i;
}
}
测试类中
TreeMap<Student, String> map = new TreeMap<>();
Student s1 = new Student("Zhang San", 23);
Student s2 = new Student("Zhang Ban", 23);
Student s3 = new Student("Wang Wu", 25);
Student s4 = new Student("Li Si", 24);
map.put(s1, "Guangdong");
map.put(s2, "Guangxi");
map.put(s3, "Fujian");
map.put(s4, "Beijing");
System.out.println(map);
得到结果:
{Zhang Ban(23)=Guangxi, Zhang San(23)=Guangdong, Li Si(24)=Beijing, Wang Wu(25)=Fujian}
**需求三 **:现有字符串 "aababcabcdabcde"
,要求统计字符串中每一个字符出现的次数,并按照所示格式输出:a(5) b(4) c(3) d(2) e(1)
。
这一需求与上一节中使用 HashMap
统计的需求相似,都是对不能预先确定种类数的内容进行统计,这时考虑使用 Map
集合统计。
使用 Map
统计,键存储统计内容,值存储统计个数。
HashMap
和 TreeMap
都可以完成统计,但前者适用于无需对结果排序的统计,而后者适用于需要对结果排序的统计。
本需求是对字符作统计,而示例中明确要求统计结果需要排序,则考虑使用 TreeMap
排序。
String str = "aababcabcdabcde";
Map<Character, Integer> stats = new TreeMap<>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (stats.containsKey(c)) {
//有
int val = stats.get(c);
stats.put(c, ++val);
} else {
//没有
stats.put(c, 1);
}
}
//输出结果,使用 StringJoiner
StringJoiner sj = new StringJoiner(" ");
stats.forEach((key, val) -> sj.add(key + "(" + val + ")"));
System.out.println(sj);
得到结果:
a(5) b(4) c(3) d(2) e(1)