TreeMap集合基本练习
一、练习:商品排序
需求
- 键:整数表示id
- 值:字符串表示商品名称
- 要求:按照id的升序排列、按照id的降序排列
测试类
package com.app.demo31_treemap_test;
import java.util.Comparator;
import java.util.TreeMap;
public class CommodityTest1{
public static void main(String[] args) {
/*
一、练习:商品排序
需求:
键:整数表示id
值:字符串表示商品名称
要求:按照id的升序排列、按照id的降序排列
注意:默认按照键从小到大进行排序(默认升序排列),也可以自己规定键的排序规则!
Integer、Double类型默认情况下都是按照升序进行排序的
String类型默认情况下是按照字母在ASCII码表中对应的数字升序进行排序的
*/
// 创建集合,键:id,值:商品名称
// 匿名内部类
/*TreeMap<Integer, String> tm = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 按照id进行降序排列
return o2 - o1;
}
});*/
// Lambda表达式
TreeMap<Integer, String> tm = new TreeMap<>((o1, o2) -> o2 - o1);
// 添加键值对元素到集合中
tm.put(3, "iphone14");
tm.put(1, "huawei");
tm.put(2, "shoubiao");
// 遍历集合
tm.forEach((id, name) -> System.out.println(id + "=" + name));
}
}
测试结果
3=iphone14
2=shoubiao
1=huawei
Process finished with exit code 0
二、练习:学生排序
需求
- 键:学生对象
- 值:籍贯
- 要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名、年龄视为同一个人。
学生类
package com.app.demo31_treemap_test;
/*
学生类
*/
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;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
/*
要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,
同姓名、年龄视为同一个人。
*/
@Override
public int compareTo(Student o) {
/*
this:表示当前要添加的元素
o:表示已经在红黑树中存在的元素
返回值:
负数:表示当前要添加的元素是小的,存左边
正数:表示当前要添加的元素是大的,存右边
0:表示当前要添加的元素已经存在,舍弃
*/
// 按照学生年龄进行升序排列
int temp = this.getAge() - o.getAge();
// 如果年龄一样,则按照姓名的字母顺序进行排序
temp = temp == 0 ? this.getName().compareTo(o.getName()) : temp;
// 如果姓名、年龄都一样,则视为同一个人。
return temp;
}
}
测试类
package com.app.demo31_treemap_test;
import java.util.Comparator;
import java.util.TreeMap;
public class StudentTest2 {
public static void main(String[] args) {
/*
练习:学生排序
需求:
键:学生对象
值:籍贯
要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名、年龄视为同一个人。
注意:
1.默认按照键从小到大进行排序(默认升序排列),也可以自己规定键的排序规则!
Integer、Double类型默认情况下都是按照升序进行排序的
String类型默认情况下是按照字母在ASCII码表中对应的数字升序进行排序的
2.如果通过实现Comparable接口的compareTo方法来指定比较规则,
同时又通过在创建TreeMap集合时传递Comparator比较器对象来指定比较规则,
那么,会默认采用第二种!
3.如果默认的排序规则已经无法满足当前需求时,程序运行时就会报错!此时就需要你自己指定比较规则!
*/
// 创建集合,键:学生对象,值:籍贯
TreeMap<Student, String> tm = new TreeMap<>((o1, o2) -> {
// 按照学生年龄进行升序排列
int temp = o1.getAge() - o2.getAge();
// 如果年龄一样,则按照姓名的字母顺序进行排序
temp = temp == 0 ? o1.getName().compareTo(o2.getName()) : temp;
// 如果姓名、年龄都一样,则视为同一个人。
return temp;
});
// 创建学生对象
Student s1 = new Student("zhangsan", 34);
Student s2 = new Student("lisi", 34);
Student s3 = new Student("wangwu", 32);
Student s4 = new Student("angelababy", 34);
Student s5 = new Student("angelababy", 34);
Student s6 = new Student("zhaoliu", 31);
// 添加键值对元素到集合中
tm.put(s1, "江苏");
tm.put(s2, "浙江");
tm.put(s3, "湖南");
tm.put(s4, "黑龙江");
tm.put(s5, "石家庄");
tm.put(s6, "广西");
// 遍历集合
tm.forEach((student, s) -> System.out.println(student + "=" + s));
}
}
测试结果
Student{name = zhaoliu, age = 31}=广西
Student{name = wangwu, age = 32}=湖南
Student{name = angelababy, age = 34}=石家庄
Student{name = lisi, age = 34}=浙江
Student{name = zhangsan, age = 34}=江苏
Process finished with exit code 0
三、练习:统计个数
需求
-
字符串:“aababcabcdadcde”
-
请统计字符串中每一个字符出现的次数,并按照以下格式输出。
-
输出结果:
a(5)b(4)c(3)d(2)e(1)
分析
-
看到统计,就要想到计数器思想,但是由于统计的东西太多,计数器很不方便。
-
因此,要有新的统计思想:利用Map集合进行统计
如果没有要求对结果进行排序,默认使用HashMap
如果要求对结果进行排序,使用TreeMap
键:表示要统计的内容
值:表示次数
-
那么我们可以看到输出结果是:a、b、c、d、e,这样出现的,说明是需要按照字母顺序进行升序排列的。
-
因此,要完成这个需求,就需要用到TreeMap集合
-
String类型默认情况下是按照字母在ASCII码表中对应的数字升序进行排序的。
测试类
package com.app.demo31_treemap_test;
import java.util.StringJoiner;
import java.util.TreeMap;
public class CountTest3 {
public static void main(String[] args) {
/*
练习:统计个数
需求:
字符串:"aababcabcdabcde"
请统计字符串中每一个字符出现的次数,并按照以下格式输出。
输出结果:
a(5)b(4)c(3)d(2)e(1)
分析:
1.看到统计,就要想到计数器思想,但是由于统计的东西太多,计数器很不方便。
2.因此,要有新的统计思想:利用Map集合进行统计
3.如果没有要求对结果进行排序,默认使用HashMap
如果要求对结果进行排序,使用TreeMap
键:表示要统计的内容
值:表示次数
4.那么我们可以看到输出结果是:a、b、c、d、e,这样出现的,说明是需要按照字母顺序进行升序排列的。
因此,要完成这个需求,就需要用到TreeMap集合。
5.String类型默认情况下是按照字母在ASCII码表中对应的数字升序进行排序的
*/
// 1.定义字符串
String str = "aababcabcdabcde";
// 3.创建TreeMap集合,键:字符,值:次数
TreeMap<Character, Integer> tm = new TreeMap<>();
// 2.遍历字符串,依次得到每个字符
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 4.判断当前字符是否存在于Map集合中
if (tm.containsKey(c)) {
// a.是,则说明存在,该字符不是第一次出现,在原有的次数上 +1
// 根据键对象获取值对象
int count = tm.get(c);
// 表示该字符又出现了1次,次数+1
count++;
// 将新的数据添加到Map集合中
tm.put(c, count);
}else {
// b.否,则说明不存在,该字符是第一次出现,记录次数为1
tm.put(c, 1);
}
}
// 5.循环结束!统计完成!遍历集合,并按照指定的格式进行拼接
// a(5)b(4)c(3)d(2)e(1)
// 方式1:StringBuilder
StringBuilder sb = new StringBuilder();
tm.forEach((key, value) -> sb.append(key).append("(").append(value).append(")"));
// 打印结果
System.out.println(sb);
System.out.println("-------------------------");
// 方式2:StringJoiner
StringJoiner sj = new StringJoiner("", "", "");
tm.forEach((key, value) -> sj.add(key + "").add("(").add(value + "").add(")"));
// 打印结果
System.out.println(sj);
System.out.println("-------------------------");
// 方式3:直接拼接
tm.forEach((key, value) -> System.out.print(key + "(" + value + ")"));
}
}
测试结果
a(5)b(4)c(3)d(2)e(1)
-------------------------
a(5)b(4)c(3)d(2)e(1)
-------------------------
a(5)b(4)c(3)d(2)e(1)
Process finished with exit code 0
四、总结
1、TreeMap集合的特点是什么?
- 键:不重复、无索引、可排序
- 底层基于红黑树实现排序,增删改查性能较好
2、TreeMap集合排序的两种方式什么?
- 实现Comparable接口,指定比较规则
- 创建集合时传递Comparator比较器对象,指定比较规则