JAVA-第二部分-常用类、集合及其数据结构

411 阅读7分钟

Object类

  • 每个类都使用Oject作为父类,都可以使用其中的方法

toString

  • 直接打印对象的名字,就是调用对象的toString方法
String s = p1.toString();
System.out.println(s);
System.out.println(p1);
  • 重写toString方法,输出其中的变量成员
//重写toString方法
@Override
public String toString() {
    return "Person{" +
            "name='" + name + ''' +
            ", age=" + age +
            '}';
}

equals

  • 默认的方法是比较值
public boolean equals(Object obj) {
    return (this == obj);
}
  • 重写比较对象的属性
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    //getClass()获取类,使用反射技术
    if (o == null || getClass() != o.getClass()) return false;
    //向下转型
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

Objects

  • 防止空指针异常
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}
String s1 = "abc";
String s2 = "cbv";
System.out.println(Objects.equals(s1, s2));

Date

  • 表示特定的瞬间,精确到毫秒
  • 一个时间点,一刹那时间
  • 可以对时间和日期进行计算
  • 当前系统时间到1970年1月1日 00:00:00(英国格林威治时间)经历了多少毫秒,返回long类型
System.out.println(System.currentTimeMillis());
  • 系统的时间日期
Date d = new Date();
System.out.println(d);
  • 将毫秒准换为时间日期
Date d1 = new Date(1627076830000L);
System.out.println(d1);
  • 将日期转换为毫秒
Long time = d.getTime();
System.out.println(time);

DateFormat

  • 时间日期格式化
  • 抽象类,无法直接使用,需要使用SimpleDateFormat
  • 日期转为字符串
//年月日-时分秒
String dateFormatStr = "yyyy.MM.dd - HH:mm:ss";
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
System.out.println(dateFormat.format(d));
  • 字符串转为日期
  • parse声明了异常,如果字符串和格式不一样,程序会抛出异常,要么throw;要么try catch
public static void main(String[] args) throws ParseException {
    //年月日-时分秒
    String dateFormatStr = "yyyy.MM.dd - HH:mm:ss";
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
    System.out.println(dateFormat.parse("2014.5.6 - 23:55:23"));
}

Calendar

  • 日历
  • 月少一个,国外7月,国内8月;星期多一天,国外2,国内1
  • 抽象类,通过静态方法获取对象
Calendar c= Calendar.getInstance();
  • 通过字段获取具体的值
System.out.println(c.get(Calendar.DAY_OF_WEEK));
  • 设置字段的值
c.set(Calendar.YEAR, 2010);
//同时设置年月日
c.set(2011,3,7);
  • 修改指定的字段的值
c.add(Calendar.YEAR,-2);
  • 转换成Date形式
System.out.println(c.getTime());

System

  • 返回当前时间的毫秒
System.out.println(System.currentTimeMillis());
  • 数组复制,将src数组从第0个起,复制到dest数组第0个起的3个元素
System.arraycopy(src,0,dest,0,3);
System.out.println(Arrays.toString(dest));

StringBuilder

  • 字符串缓冲区,提高字符串的操作效率
  • 长度可以变化的字符串,底层也是一个数组,但是没有被final修饰
  • 底层初始长度为16,并且会自动扩容
  • 构造,将String转换成stringBuilder
StringBuilder stringBuilder = new StringBuilder();
System.out.println(stringBuilder);

StringBuffer stringBuffer2 = new StringBuffer("abc");
System.out.println(stringBuffer2);
  • 添加任意类型数据的字符串,返回当前对象自身,返回的是this,所以无需接收返回值
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abc");
stringBuilder.append(true);
stringBuilder.append('c');
stringBuilder.append(9.6);
System.out.println(stringBuilder.append(100L));
//链式编程,方法的返回值是一个对象
stringBuilder.append("ab").append(false).append('b').append(9.8);
  • toString,将StringBuilder转换成String
System.out.println(stringBuilder.toString());

包装类

  • 基本数据类型,没有方法操作这些数据
  • 通过一个类,把基本数据类型包装起来,用类中的方法操作数据
  • 装箱,把基本数据类型转换成包装类
//被移除
Integer integer1 = new Integer(8);
System.out.println(integer1);
Integer integer2 = new Integer("1");
System.out.println(integer2);
//静态方法
Integer integer3 = Integer.valueOf(8);
System.out.println(integer3);
Integer integer4 = Integer.valueOf("10");
System.out.println(integer4);
  • 拆箱,包装类转换成基本数据类型
int i = integer4.intValue();
System.out.println(i);
  • 包装类和基本数据类型会自动相互转换
  • 基本数据类型和字符串类型的相互转换
//基本数据类型->String
String s1 = 8 + "";
System.out.println(s1+200);
String s2 = Integer.valueOf(89).toString();
System.out.println(s2+200);
String s3 = String.valueOf(11);
System.out.println(s3+200);
//String->基本数据类型
int i = Integer.parseInt(s3);
System.out.println(i + 200);

Collection

  • 定义所有单列集合的共性的方法,没有带索引的方法 | Collection | | | :---: | :---: | | List接口 | Set接口 | | Vector | TreeSet | | ArrayList | HashSet | | LinkedList | LinkedHashSet(继承HashSet) |

  • 添加元素

Collection<String> coll = new ArrayList<>();
coll.add("xiaoming");
coll.add("zhangsan"); // 一般返回都是true
coll.add("lisi");
coll.add("wangwu");
coll.add("zhaoliu");
coll.add("chenqi");
System.out.println(coll.toString());
  • 删除
//删除成功返回true,不存在返回false
coll.remove("xiaoming");
  • 是否包含某个元素
boolean res = coll.contains("lisi");
System.out.println(res);
  • 是否为空
boolean empty = coll.isEmpty();
System.out.println(empty);
  • 长度
int size = coll.size();
System.out.println(size);
  • 转换成数组
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}
  • 清空所有集合
coll.clear();
System.out.println(coll.toString());
System.out.println(coll.isEmpty());

List接口

  • 有序
  • 允许存储重复的元素
  • 有索引,可以用普通的for循环遍历
  • 在指定索引处添加方法
list.add(3,"xiaoming");
  • 移除元素,并返回被移除的内容
String removeStr = list.remove(2);
  • 替换元素,并返回被替换的内容
String setStr = list.set(1, "zhangsan");
  • 遍历方法,get获取
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
System.out.println("------------------");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}
System.out.println("------------------");
for (String s : list) {
    System.out.println(s);
}

ArrayList

  • 底层数据结构是数组结构,实现是多线程的
  • 如果要添加元素,要创建新数组,数组长度+1
  • 查询比较多,可以使用
  • add(int idx, int element) 将原有idx的元素往后推
  • set(int idx, int element) 修改idx的元素

LinkedList

  • 不能使用多态创建,不能使用其中的子类方法
  • 链表结构,多线程,查询慢,增删快
  • 添加头尾
list.addFirst("xiaoming");
//效果跟addFirst一致
list.push("wangwu");
list.addLast("zhangsan");
System.out.println(list);
  • 获取头尾
String getFirstStr = list.getFirst();
String getLastStr = list.getLast();
System.out.println(getFirstStr);
System.out.println(getLastStr);
  • 删除头尾,返回删除的内容
String removeFirstStr = list.removeFirst();
//与removeFirst效果一致
String popStr = list.pop();
String removeLastStr = list.removeLast();
System.out.println(removeFirstStr);
System.out.println(removeLastStr);
System.out.println(popStr);
  • 队列使用
Queue<String> strings = new LinkedList<>();
//添加元素,添加失败返回false
strings.offer("zhangsan");
strings.offer("lisi");
strings.offer("wangwu");
//看第一个元素,不存在返回null
String peek = strings.peek();
System.out.println(peek);
//返回第一个元素,并从队列中删除,不存在返回null
String poll = strings.poll();
System.out.println(poll);

Vector

  • 底层是数组,单线程

Set接口

  • 不允许存储重复元素
  • 没有索引
  • HashSet是无序的,存取元素的顺序可能不一致

HashSet

  • 不保证迭代的顺序,不保证顺序恒久不变,多线程
  • 底层是哈希表结构,查询速度非常快
  • 不允许存储相同内容的原理,Set集合在调用add的时候,会调用hasCodeequals方法,判断元素是否重复;存储的元素必须重写hasCodeequals方法
HashSet<String> set = new HashSet<>();
String s1 = new String("abc");
String s2 = new String("abc");
set.add(s1);
set.add(s2);
set.add("重地");
set.add("通话");
set.add("abc");
System.out.println("abc".hashCode());
System.out.println(set);

image.png

LinkedHashSet

  • 底层是哈希表+链表,多了一条链表记录元素存储顺序,保证元素有序

TreeSet

  • 非同步,底层是二叉树(红黑树),性能没有hashset好,不允许有null,有序

哈希值

  • 十进制的整数,由系统随机给出,是对象的地址值,是一个逻辑地址,模拟的出来的地址,并不是数据实际存储的物理地址
  • 获取哈希值
Person p = new Person();
System.out.println(p);
System.out.println(p.hashCode());
//输出,toString方法输出的地址值,就是哈希值的十六进制形式
com.mzx.java.DemoList.DemoSet.Person@4617c264
1175962212
  • 字符串类的哈希值
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
//输出,字符串一样,输出的哈希值一样,重写了hasCode方法
96354
96354

哈希表

  • 1.8前 数组+链表
  • 1.8后 数组+红黑树
  • 查询速度快
  • 数据结构:把元素进行分组,存储哈希值
  • 链表/红黑树结构,把相同哈希值连接到一起,如果某个数组下面的元素长度超过8个,用红黑树结构 image.png

Iterator

  • 迭代器
Iterator interator = coll.iterator();
//是否有下一个元素
boolean res = interator.hasNext();
System.out.println(res);
//取出下一个
System.out.println(interator.next());
  • 循环取出
while (iterator.hasNext()) {
    System.out.println(iterator.next());
    System.out.println(iterator.hasNext());
}

实现原理

  • 实现类对象,指针指向集合的-1索引
  • next()取出下一个元素,指针向后移动一位

增强for循环

  • 底层也是迭代器
  • 所有单列集合都可以使用
  • 被遍历的目标只能是集合或者数组
for (String str : coll) {
    System.out.println(str);
}

数据结构

  • 先进后出
  • 入口出口在一侧 image.png

队列

  • 先进先出 image.png

数组

  • 查询快,增删慢
  • 有序,有索引
  • 数组地址是连续的,通过数组的首地址可以找到数组,通过索引快速查找某一个元素
  • 数组的长度是固定的,增删必须创建一个新数组,把源数组的数据复制过来,将新数组的地址赋值给变量,源数组会在内存中被销毁
  • 在堆内存中,频繁地创建数组,复制数组中的元素,销毁数组,效率低下

链表

  • 查询慢,增删快

  • 链表中的地址不是连续的,每次查询元素,都要从头开始查询

  • 链表借口,增删元素,对链表的整体结构没有影响

  • 链表中的每一个元素称之为节点,一个节点包含了一个数据域(存储数据),两个指针域(存储地址) | 自己的地址 | 数据 | 下一个节点的地址 | |:----:|:----:|:----:|

  • 单向链表,只有一条链子,不能保证元素的顺序,存取顺序有可能不一致

  • 双向链表,有两条链子,有一条链子专门记录元素的顺序,有序

  • 第一条链记录本节点和下一个节点的地址,不保证顺序;第二条链记录顺序

  • 二叉树,分支不能超过两个,左(右)孩子(子树)
  • 平衡树,左子树的数量和右子树的数量相等
  • 不平衡树,左子树的数量和右子树的数量不相等

排序树(查找树)

  • 在二叉树的基础上,元素上有大小顺序,左子树小,右子树大
  1. 左子树的所有节点都比根节点小
  2. 右子树的所有节点都比根节点大
  3. 左子树小于节点,右子树要大于节点

红黑树

  • 趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数之比不能超过两倍
  1. 节点可以是红色的或者黑色的
  2. 根节点是黑色的
  3. 叶子节点(空节点,接下去没有子节点)是黑色的
  4. 每个红色的节点的子节点都是黑色的,不能有两个连续的红色节点
  5. 任何一个节点到其每一个叶子节点的所有路径上黑色的节点数相同

Collections

  • Collection的工具类
  • 添加多个元素
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"a","b","c","d","e","f");
  • 打乱集合的顺序
Collections.shuffle(list);
  • 排序,默认是升序,被排序的集合中的元素必须实现Comparable,重写接口中的CompareTo定义排序的方式
Collections.sort(list);
System.out.println(list);

ArrayList<Person> list1 = new ArrayList<>();
list1.add(new Person("xiaoming",18));
list1.add(new Person("zhangsan",15));
list1.add(new Person("lisi",20));
System.out.println(list1);
Collections.sort(list1);
System.out.println(list1);
//重写
@Override
public int compareTo(Person o) {
    //(this - 参数)返回值大于0,升序排序
    return this.getAge() - o.getAge();
}

Comparable与Comparator

  • Comparable,自己(this)与别人(参数)进行比较,自己需要实现Comparable,重写接口中的CompareTo定义排序的方式
  • Comparator,相当于找一个第三方的裁判,比较两个
  • 匿名内部类实现自定义的排序方法
ArrayList<Character> list = new ArrayList<>();
Collections.addAll(list,'a','b','c','d','e','f');
Collections.shuffle(list);
System.out.println(list);
Collections.sort(list, new Comparator<Character>() {
    @Override
    public int compare(Character o1, Character o2) {
        return o2 - o1;
    }
});
System.out.println(list);

ArrayList<Person> list1 = new ArrayList<>();
list1.add(new Person("xiaoming",18));
list1.add(new Person("zhangsan",15));
list1.add(new Person("lisi",20));
list1.add(new Person("wangwu",22));
list1.add(new Person("zhaoliu",20));
System.out.println(list1);
Collections.sort(list1, new Comparator<Person>() {
    @Override
    public int compare(Person o1, Person o2) {
        int res = o2.getAge() - o1.getAge();
        if (res == 0) {
            res = o2.getName().charAt(0) - o1.getName().charAt(0);
        }
        return res;
    }
});
System.out.println(list1);

泛型

  • 当不知道需要使用什么数据类型的时候,使用泛型
  • 不使用泛型,默认为Object,可以存储任意类型的数据,但是不安全,引发异常
  • 使用泛型,避免类型转换,把运行的异常提前到编译期(编写代码的时候)
  • 字母无所谓
  • E e,Element元素,未知的数据类型;创建集合对象的时候,就会确定泛型的数据类型
public E set(int index, E element) {
    Objects.checkIndex(index, size);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
  • T t,Type类型,

自定义泛型

public class GenericClass<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}
  • 含有泛型的方法
public <M> void method(M m) {
    System.out.println(m);
}
//静态方法
public static <S> void methodStatic(S s) {
    System.out.println("methodStatic - " + s);
}

//使用
gc.method("xiaoming");
gc.method(1);
gc.method(10.888);
GenericClass.methodStatic("zhangsan");
GenericClass.methodStatic(123.33);
GenericClass.methodStatic(true);
  • 含有泛型的接口
//接口
public interface GenericInterface<I> {
    void methodInterface(I i);
}
//第一种使用方式,直接在实现类中指定泛型类型
public class GenericInterfaceImpl implements GenericInterface<String>{

    @Override
    public void methodInterface(String s) {
        System.out.println(s);
    }
}
GenericInterfaceImpl gi = new GenericInterfaceImpl();
gi.methodInterface("zhangsan");

//第二种使用方式,创建对象时指定泛型
public class GenericInterfaceImpl<S> implements GenericInterface<S>{
    
    @Override
    public void methodInterface(S s) {
        System.out.println(s);
    }
}
GenericInterfaceImpl<Integer> gi = new GenericInterfaceImpl();
gi.methodInterface(1);

泛型通配符

  • <?>
  • 代表任意的数据类型,不能创建对象使用,只能作为方法的参数使用
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);

ArrayList<String> list2 = new ArrayList<>();
list2.add("zhangsan");
list2.add("lisi");

printArray(list1);
printArray(list2);

public static void printArray(ArrayList<?> list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

受限泛型

  • 上限,? extneds E,代表泛型只能是E类型的子类/本身
  • 下限,? super E ,代表泛型只能是E类型父类/本身
public static void main(String[] args) {

    Collection<Integer> list1 = new ArrayList<Integer>();
    Collection<String> list2 = new ArrayList<String>();
    Collection<Number> list3 = new ArrayList<Number>();
    Collection<Object> list4 = new ArrayList<Object>();

    getElement1(list1);
    //list2不是Number的子类或者本身
    getElement1(list2);//报错
    getElement1(list3);
    //list4不是Number的子类或者本身
    getElement1(list4);//报错
    
    //list1/2不是Number的父类或者本身
    getElement2(list1);//报错
    getElement2(list2);//报错
    getElement2(list3);
    getElement2(list4);

    /*
        类与类之间的继承关系
        Integer extends Number extends Object
        String extends Object
     */
}

// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}

可变参数

  • 传递的个数不确定,类型确定
  • 底层就是一个数组,根据传递参数个数不同,创建不同长度的数据,用来存储这些参数
  • 一个方法的参数列表,只能有一个可变参数
  • 如果参数有多个,可变参数必须写在参数列表的末尾
/调用
System.out.println(add(1,2,3,4,5,6,7,8,9));

public static int add(int ... nums) {
    int res = 0;
    for (int i = 0; i < nums.length; i++) {
        res += nums[i];
    }
    return res;
}
  • 可变参数特殊写法
public static void print(Object ... o) {
    for (Object o1 : o) {
        System.out.println(o1);
    }
}

Map

  • Map<K, V>
  • 将键映射到值
  • 必须保证Key唯一,作为Key的元素,必须重写hasCodeequals方法,保证Key唯一

HashMap

  • HashSet底层使用了HashMapKey
public HashSet() {
    map = new HashMap<>();
}
  • 底层是哈希表,1.8前使用数组+单向链表;1.8后使用数组+单向链表/红黑树
  • 无序集合
  • put添加元素,如果Key重复则返回被替代的元素,如果不存在返回null
Map<String, String> map = new HashMap<>();
String returnStr = map.put("zhangsan","zhangsan1");
System.out.println(returnStr);
returnStr = map.put("zhangsan","zhangsan2");
System.out.println(returnStr);
  • remove删除指定的Key,返回Value,不存在返回null
map.put("lisi","lisi2");
map.put("wangwu","wangwu2");
map.put("zhaoliu","zhaoliu2");
map.put("chenqi","chenqi2");
map.put("huangba","huangba2");
System.out.println(map);
System.out.println(map.remove("zhaoliu"));
System.out.println(map.remove("dd"));
System.out.println(map);
  • get获取value,没有返回null
System.out.println(map.get("www"));
System.out.println(map.get("wangwu"));
  • contains是否包含指定的KeyValue
System.out.println(map.containsKey("wangwu")); //true
System.out.println(map.containsKey("zhaooliu"));//false

System.out.println(map.containsValue("wangwu2"));//true
System.out.println(map.containsValue("wangwu"));//false
  • 遍历
Set<String> kSet = map.keySet();
kSet.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        System.out.println(s + " = " + map.get(s));
    }
});
System.out.println("--------------");
for (String s : kSet) {
    System.out.println(s + " = " + map.get(s));
}
  • 存储自定义类型
  • KeyString,已经重写hasCodeequals方法
HashMap<String, Person> map = new HashMap<>();
map.put("beijing",new Person("zhangsan",18));
map.put("chongqing",new Person("lisi",23));
map.put("hangzhou",new Person("wangwu",12));
map.put("shanghai",new Person("zhaoliu",15));
map.put("shenzhen",new Person("chenqi",20));
for (Map.Entry<String, Person> stringPersonEntry : map.entrySet()) {
    System.out.println(stringPersonEntry.getKey() + " = " + stringPersonEntry.getValue());
}
  • KeyPerson,需要重写hasCodeequals方法
//重写
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}
//使用
HashMap<Person, String> map2 = new HashMap<>();
map2.put(new Person("zhangsan",18),"beijing");
map2.put(new Person("lisi",23),"chongqing");
map2.put(new Person("wangwu",12),"hangzhou");
map2.put(new Person("zhaoliu",15),"shanghai");
map2.put(new Person("chenqi",20),"shenzhen");
map2.put(new Person("chenqi",20),"shenzhen");
map2.put(new Person("chenqi",20),"shenzhen");
for (Map.Entry<Person, String> stringPersonEntry : map2.entrySet()) {
    System.out.println(stringPersonEntry.getKey() + " = " + stringPersonEntry.getValue());
}

Entry

  • Map的内部接口
  • 用来记录键与值,键值对对象,键与值的映射关系
  • 类似Iterator遍历集合
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry<String, String> s : set) {
    System.out.println(s.getKey() + " = " + s.getValue());
}

LinkedHashMap

  • 有序,不允许重复
  • 哈希表+链表,保证迭代顺序
  • 继承HashMap
Map<String, String> hashMap = new HashMap<>();
hashMap.put("chenqi","chenqi2");
hashMap.put("huangba","huangba2");
hashMap.put("lisi","lisi2");
hashMap.put("wangwu","wangwu2");
hashMap.put("zhaoliu","zhaoliu2");
System.out.println(hashMap);
System.out.println("---------------");
Map<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("chenqi","chenqi2");
linkedHashMap.put("huangba","huangba2");
linkedHashMap.put("lisi","lisi2");
linkedHashMap.put("wangwu","wangwu2");
linkedHashMap.put("zhaoliu","zhaoliu2");
System.out.println(linkedHashMap);

Hashtable

  • 不允许存储空,是同步的,单线程
  • 被取代
  • 子类Properties仍在使用,唯一一个和IO流相结合的集合

TreeMap

  • 加入后有序,默认升序
  • 基本使用
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(10,32);
map.put(111,42);
map.put(20,12);
map.put(5,53);
//默认升序
//最小的key
System.out.println(map.firstKey());
//直接取出最小的key的键值对
System.out.println(map.pollFirstEntry());
//最大的key
System.out.println(map.lastKey());
//最大的key的键值对
System.out.println(map.lastEntry());
  • 取顶和取底
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(1, "xiaoming - " + 1);
treeMap.put(3, "xiaoming - " + 1);
treeMap.put(8, "xiaoming - " + 1);
treeMap.put(10, "xiaoming - " + 1);
Integer lowerKey = treeMap.lowerKey(10);
// 8 不包括10
System.out.println(lowerKey);
Integer floorKey = treeMap.floorKey(10);
// 10 包括10
System.out.println(floorKey);
Integer higherKey = treeMap.higherKey(3);
// 8 不包括3
System.out.println(higherKey);
Integer ceilingKey = treeMap.ceilingKey(3);
//3 包括3
System.out.println(ceilingKey);
  • 设置降序
TreeMap<Integer, Integer> map = new TreeMap<>((o1, o2) -> o2 - o1);
  • 自定义类,实现排序
//调用
TreeMap<Person, Integer> map = new TreeMap<>(new ComparatorPerson());
map.put(new Person("zhangsan",132),13);
map.put(new Person("zhangsan",1552),14);
map.put(new Person("zhangsan",12),12);

//实现接口
class ComparatorPerson implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        return o1.age - o2.age;
    }
}

//或者key实现Comparable接口
class Person implements Comparable<Person>{
    //其他代码...
    @Override
    public int compareTo(Person o) {
        return o.age - this.age;
    }
}

集合一次性添加多个元素

  • 集合中存储的元素个性已经确定,在不改变时使用
  • of方法只适用于listSetMap
  • 返回的是一个不能改变的集合
  • SetMap在调用of的时候,不能有重复的元素
List<? extends Serializable> list = List.of(1, 2, 4, "b");
System.out.println(list);
Set<String> set = Set.of("a", "b", "c");
System.out.println(set);
Map<Integer, String> map = Map.of(1, "xiaoming", 2, "lisi", 3, "wangwu");
System.out.println(map);