TreeMap的基本了解

TreeMap 的特点

TreeMap 是 Java 集合框架中的一个基于红黑树(Red-Black Tree)实现的有序映射。红黑树是一种自平衡的二叉查找树,能够保证插入、删除和查找操作的时间复杂度为 O(log n)。TreeMap 的主要特点包括:

  • 有序性:TreeMap 中的键值对按照键的自然顺序(Comparable 接口)或自定义顺序(Comparator 接口)进行排序。
  • 唯一键:TreeMap 中的键必须是唯一的,不允许重复。
  • 线程不安全:TreeMap 不是线程安全的,如果在多线程环境中使用,需要外部同步机制。

TreeMap 的基本应用

TreeMap 适用于需要按键有序存储的场景,例如按字母顺序或数字顺序排序的键值对集合。以下是一个基本应用的示例:

import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap<>();
        treeMap.put(3, "Apple");
        treeMap.put(1, "Banana");
        treeMap.put(2, "Cherry");
        System.out.println(treeMap); // 输出: {1=Banana, 2=Cherry, 3=Apple}
    }
}

TreeMap 的常用方法

以下是 TreeMap 的一些常用方法:

  1. put(K key, V value):向 TreeMap 中添加键值对。
  2. get(Object key):根据键获取对应的值。
  3. remove(Object key):删除指定键的键值对。
  4. firstKey()lastKey():分别获取第一个和最后一个键。
  5. headMap(K toKey)tailMap(K fromKey):获取键小于 toKey 或大于等于 fromKey 的子映射。

示例代码:

import java.util.TreeMap;

public class TreeMapMethodsExample {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap<>();
        treeMap.put(3, "Apple");
        treeMap.put(1, "Banana");
        treeMap.put(2, "Cherry");

        System.out.println(treeMap.get(2)); // 输出: Cherry
        System.out.println(treeMap.firstKey()); // 输出: 1
        System.out.println(treeMap.lastKey()); // 输出: 3
    }
}
实例:
package test._TreeMap;

import java.util.Comparator;
import java.util.TreeMap;

public class test01_TreeMap {
    public static void main(String[] args) {
        /*
        TreeMap集合:基本应用
        需求1:
        键:整数表示id
        值:字符串表示商品名称
        要求1:按照id的升序排列
        要求2:按照id的降序排列
        */

       //1.创建集合对象
       //Integer Double 默认情况下都是按照升序排列的
       //String 按照字母用ASCII码表中对应的数字升序进行排列
       //abcdefg ...
        TreeMap tm = new TreeMap<>(new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        //2.添加元素
        tm.put(1,"我的");
        tm.put(2,"你的");
        tm.put(3,"啊看我的啊");
        tm.put(4,"答 答");
        tm.put(5,"发发我");

        //3.打印集合
        System.out.println(tm);
    }
}

键为自定义对象的 TreeMap

如果 TreeMap 的键是自定义对象,该对象必须实现 Comparable 接口或传入一个 Comparator 对象,以确保键的可排序性。以下是一个示例:

import java.util.TreeMap;

class Person implements Comparable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class CustomObjectTreeMapExample {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap<>();
        treeMap.put(new Person("Alice", 25), "Engineer");
        treeMap.put(new Person("Bob", 30), "Doctor");
        treeMap.put(new Person("Charlie", 35), "Teacher");

        System.out.println(treeMap);
        // 输出: {Alice (25)=Engineer, Bob (30)=Doctor, Charlie (35)=Teacher}
    }
}
实例:
package test._TreeMap;

public class Student implements Comparable {
    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 i = this.getAge() - o.getAge();
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        return i;
    }
}
package test._TreeMap;

import java.util.TreeMap;

public class test02_TreeMap {
    public static void main(String[] args) {
        //1.创建TreeMap对象
        TreeMap tm = new TreeMap<>();

        //2.创建学生对象
        Student s1 = new Student("bhangsan",20);
        Student s2 = new Student("aisi",20);
        Student s3 = new Student("wangwu",22);

        //3.添加元素
        tm.put(s1,"江苏");
        tm.put(s2,"广州");
        tm.put(s3,"深圳");
        //这里的Student就是自定义的类型,没有从小到大的默认排序,需要在Student类中进行定义排序规则
        //打印集合
        System.out.println(tm);
    }
}

使用 Comparator 自定义排序

如果不想修改自定义对象的类,可以通过传入 Comparator 对象来实现排序:

import java.util.Comparator;
import java.util.TreeMap;

class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return name + " ($" + price + ")";
    }
}

public class ComparatorTreeMapExample {
    public static void main(String[] args) {
        Comparator priceComparator = Comparator.comparingDouble(Product::getPrice);
        TreeMap treeMap = new TreeMap<>(priceComparator);

        treeMap.put(new Product("Laptop", 999.99), 10);
        treeMap.put(new Product("Phone", 699.99), 20);
        treeMap.put(new Product("Tablet", 399.99), 30);

        System.out.println(treeMap);
        // 输出: {Tablet ($399.99)=30, Phone ($699.99)=20, Laptop ($999.99)=10}
    }
}
实例:
package test._TreeMap;

import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.function.BiConsumer;

public class test03_TreeMap {
        /* 需求:
        字符串“aababcabcdabcde”
        请统计字符串中每一个字符出现的次数,并按照以下格式输出
        输出结果:
        a(5)b(4)c(3)d(2)e(1)

        新的统计思想:利用map集合进行统计
        如果题目中没有要求对结果进行排序,默认使用HashMap
        如果题目中要求对结果进行排序,请使用TreeMap

        键:表示要统计的内容
        值:表示次数
        */
        public static void main(String[] args) {
            //1.定义字符串
            String s = "aababcabcdabcde";

            //3.创建集合
            TreeMap tm = new TreeMap<>();

            //2.遍历字符串把字符一个个取出来
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);

                //4.开始判断字符在集合中是否存在,为统计字符次数做准备
                //拿着c到集合中判断是否存在
                //存在,表示当前字符又出现了一次
                //不存在,表示当前字符是第一次出现
                if(tm.containsKey(c)){
                    //存在,就把次数拿出来
                    int count = tm.get(c);
                    count++;
                    tm.put(c,count);
                }else {
                    //不存在
                    tm.put(c,1);
                }
            }

            //5.遍历集合,并按照格式进行拼接输出
            //a(5)b(4)c(3)d(2)e(1)
            StringBuilder sb = new StringBuilder();
            tm.forEach((key, value)-> sb.append(key).append("(").append(value).append(")"));
            System.out.println(sb);

            StringJoiner sj = new StringJoiner("","","");
//            sj.add()里面只能田家庵字符串,所以+""把括号里面变成字符串
            tm.forEach((key, value)-> sj.add(key+"").add("(").add(value+"").add(")"));
            System.out.println(sj);
        }

}

以上内容涵盖了 TreeMap 的特点、基本应用、常用方法以及如何将自定义对象作为键的详细说明和代码示例。

总结:

以下是提取的文字:

1. TreeMap集合的特点是怎么样的?
   - 不重复、无索引、可排序
   - 底层基于红黑树实现排序,增删改查性能较好

2. TreeMap集合排序的两种方式
   - 实现Comparable接口,指定比较规则
   - 创建集合时传递Comparator比较器对象,指定比较规则

(比如有时候要用降序,但是Comparable接口是默认升序的,所以这时候就要用Comparator比较器了,或者说默认的一般按abcd来排序,但是现在要拿字符串的长度进行排序,那么Comparable接口就满足不了了,要用Comparator比较器来实现)

你可能感兴趣的:(java,开发语言)