JavaSE(十四)集合

本文详细介绍了Java集合框架中的Collection接口及其子接口List和Set的特点,包括ArrayList、LinkedList和Vector的实现原理与使用场景。同时,文章也探讨了Set的实现类如HashSet、LinkedHashSet和TreeSet。对于Map接口,文章讲解了HashMap、LinkedHashMap、TreeMap和Hashtable的特性和使用注意事项,以及集合工具方法的应用。

集合

  • 集合类型,好多个类型,JDK提供好的 位于java.util包中 需要显示导入进来;

  • 集合类型和数组类似,都是容器

  • 数组使用起来不太方便,集合类型使用起来非常简单

  • 数组 数组元素;集合 集合元素;集合中只能存放对象,集合元素必须都是对象,基本数据类型的值需要转换为包装类型

1.1.Collection接口

  • Collection集合元素是单值,一个对象就是一个集合元素

Collection父接口定义的方法

    /**
     * Collection接口中定义的非常常用的方法
     */
    private static void method2() {
        Collection collection = new ArrayList();
        //isEmpty方法 判断是否是一个空集合
        System.out.println("是否是空集合 元素个数为0: " + collection.isEmpty());
        //添加不需要考虑扩容 删除的时候不需要考虑元素移动
        //add方法用于向集合中添加集合元素对象
        collection.add("java");
        //int ->Integer 集合中只能放对象 基本数据类型都要转换为包装类型
        collection.add(123);
        collection.add(new Monkey());
        //remove方法删除 指定对象;如果删除成功返回true
        System.out.println(collection.remove(123));
        System.out.println("contains集合中是否包含指定对象: " + collection.contains("java"));
        //clear方法 用于清空集合
        collection.clear();
        //size方法 用于获取集合大小  也就是集合元素的个数
        System.out.println("集合大小 集合元素个数: " + collection.size());
        //集合类型都已经重写了toString方法 内部实现是把内部每个元素的字符串形式拼接为一个字符串对象
        System.out.println(collection);
    }
​
 /**
     * Collection接口中定义的常用的方法
     */
    private static void method3() {
        Collection collection1 = new ArrayList();
        collection1.add("java1");
        collection1.add("java2");
        collection1.add("java3");
        Collection collection2 = new ArrayList();
        //addAll 添加指定集合中的所有元素
        collection2.addAll(collection1);
        collection2.add(6.9);
        collection2.add(9.9);
        collection2.add("java2");
        collection2.add("java3");
        // collection2.remove("java1");
        //containsAll 判断是否包含指定集合中的所有元素对象
        System.out.println("containsAll:  " + collection2.containsAll(collection1));
        //removeAll当前集合元素对象 只要位于 指定集合中 都进行删除(只要相等 都进行删除)
//        collection2.removeAll(collection1);
        //把集合类型 转换为 数组类型
        Object[] objects = collection2.toArray();
        System.out.println(collection2);
        System.out.println(Arrays.toString(objects));
    }

remove的注意点

 /**
     * remove方法 注意
     */
    private static void method4() {
        Collection collection = new ArrayList();
        collection.add("java");
        collection.add("java");
        //如果有多个相同对象 只删除第一个
        collection.remove("java");
        System.out.println(collection);
    }

1.1.1. List子接口

  • 集合元素是单值; List的集合元素是 有序而且可以重复的

  • /**
        * List和Set的特点
        */
       private static void method5() {
           List list = new ArrayList();
           //  List的集合元素是  有序(存取有序 添加的顺序就是存放的顺序 有索引)而且可以重复的
           list.add("java2");
           list.add("java1");
           list.add("java3");
           System.out.println(list);
     
           // Set 的集合元素是  无序(没有索引)而且不可重复的
           Set set = new HashSet<>();
           set.add("java2");
           set.add("java1");
           set.add("java3");
           System.out.println("set: " + set);
       }
1.1.1.1. List方法定义与使用

1,常用方法

/**
     * List子接口 新增方法
     */
    private static void method6() {
        //List的元素是有索引 值从0开始 索引有效取值范围[0,size-1]
        List list = new ArrayList();
        list.add("java2");
        list.add("java1");
        list.add("java3");
        list.add("java2");
        //add方法 指定索引位置 插入元素对象
        list.add(0, "python");
        //get方法 根据指定索引 获取元素对象
        Object o = list.get(3);
        System.out.println(o);
        System.out.println("indexOf指定对象首次出现的索引值: " + list.indexOf("java2"));
        System.out.println("lastIndexOf指定对象最后一次出现的索引值: " + list.lastIndexOf("java2"));
        //remove方法 根据指定索引 删除元素对象
        list.remove(0);
        //set方法 改值 根据指定索引值 使用新的元素对象替换旧的元素对象
        list.set(0, "JS");
        System.out.println(list);
    }

2,泛型的使用

 /**
     * 泛型在集合中的应用
     */
    private static void method9() {
        List<Monkey> list = new ArrayList<>();
        list.add(new Monkey());
        Monkey monkey1 = list.get(0);
        //集合中只能放对象
        List<Integer> list2 = new ArrayList<>();
    }
​
    private static void method8() {
        //泛型在集合的使用 为了约束集合元素的类型
        List<String> arr = new ArrayList();
        arr.add("java1");
        arr.add("java2");
​
        String s = arr.get(0);
        //泛型 如果不指定 统统来看Object来看
        List arr2 = new ArrayList();
        List<Object> arr3 = new ArrayList();
    }

3,泛型指定为容器类型

/**
     * List的泛型指定为 容器类型
     */
    private static void method10() {
        //<引用类型>
        List<int[]> list = new ArrayList<>();
        int[] arr1 = {12, 77, 99};
        list.add(arr1);
        System.out.println(list.size());
​
        //存放所有班级的所有学生
        //list2的集合元素类型也是List类型
        List<List<Monkey>> list2 = new ArrayList<>();
        List<Monkey> sonList1 = new LinkedList<>();
        sonList1.add(new Monkey(101, "monkey1"));
        sonList1.add(new Monkey(102, "monkey2"));
        list2.add(sonList1);
        List<Monkey> monkeys = list2.get(0);
        System.out.println(monkeys);
    }

4,List的遍历方式

 /**
     * List的遍历
     */
    private static void method11() {
        ArrayList<String> list = new ArrayList();
        list.add("java2");
        list.add("java1");
        list.add("java3");
        //1 普通for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("===============");
        //2 增强for循环
        for (String s : list) {
            System.out.println(s);
        }
        System.out.println("++++++++++++++++s");
        //3 迭代器遍历
        Iterator<String> iterator = list.iterator();
        //
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("######################");
        // 4 forEach方法遍历
//        list.forEach(new ConsumerImpl());
    }

5,forEach遍历

/**
     * forEach方法 使用匿名内部类或lambda表达式
     */
    private static void method12() {
    /*class T {
    }*/
        //List: 有序 而且 可以重复
        ArrayList<String> list = new ArrayList<>();
        list.add("java2");
        list.add("java1");
        list.add("java3");
        //匿名内部类 无名类; 一次性的类
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        System.out.println("=========");
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s + "++++++++++++++++++");
            }
        });
        System.out.println("*************");
        //JDK8之后出现的 lambda表达式 简化
        list.forEach((s) -> {
            System.out.println(s);
        });
   /*     list.add("java1");
        String s = list.get(0);
        System.out.println(list.size());
        list.remove("java1");
        list.remove(0);
        list.contains("java1");
        list.set(0, "java2");*/
    }

6,遍历注意

/**
     * 遍历过程中 如果要删除集合元素可以使用迭代器的删除或者遍历完成后进行删除
     */
    private static void method13() {
        ArrayList<String> list = new ArrayList();
        list.add("java2");
        list.add("java1");
        list.add("java3");
​
       /* int index = -1;
        for (int i = 0; i < list.size(); i++) {
            if ("java1".equals(list.get(i))) {
                index = i;
            }
        }
        //
        list.remove(index);*/
​
        //迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            if ("java1".equals(iterator.next())) {
                iterator.remove();
            }
        }
        System.out.println(list);
    }
1.1.1.2. List实现类

1,ArrayList

  • 底层是数组;数组内存空间连续的 查询性能较高 O(1) ;删除元素和指定位置新增的时候涉及到元素的移动 删除的性能较低

  • 如果使用无参构造创建ArrayList对象 ;数组第一次扩容的长度为10 ,后续的扩容都是1.5倍;

  • 推荐使用有参构造 防止底层数组多次无效扩容 给一个大致的预估值

private static void method1() {
        //推荐使用有参构造 防止底层数组多次无效扩容 预估值
        ArrayList<Monkey> arrayList = new ArrayList<>(32);
​
        //如果使用无参构造创建ArrayList对象 ;数组第一次扩容的长度为10 ,后续的扩容都是1.5倍
        ArrayList<String> arr = new ArrayList<>();
        arr.add("java1");
        arr.add("java2");
        arr.add("java3");
        arr.add("java4");
        //取元素  O(1)
        String s = arr.get(0);
        //
        String str = arr.remove(0);
        //
        arr.add(0, "python");
    }

2,LinkedList

  • 底层是 双向链表;内存空间不连续;查询性能较低 O(n),删除和指定位置新增只需要改动前后两个节点的指向 性能较高;

//节点类型 
private static class Node<E> {
    //为了存储集合元素对象
        E item;
    //next:指向下一个节点对象
        Node<E> next;
    //prev:指向前一个节点对象
        Node<E> prev;
​
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

使用

private static void method2() {
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("java1");
        linkedList.add("java2");
​
        String s = linkedList.get(1);
        linkedList.add(0, "JS");
        linkedList.remove(1);
    }

面试题: ArrayList和LinkedList的区别

3,Vector

  • 底层和ArrayList底层一模一样,底层也是Object数组

  • 区别 它是线程安全的类型;ArrayList,LinkedList线程不安全

 public static void main(String[] args) {
        Vector<String> vector = new Vector<>();
        vector.add("java");
    }
1.1.1.3.匿名内部类与lambda

1,匿名内部类

  • 匿名内部类可以应用在抽象类,接口 上面,抽象方法个数不要求

抽象类定义

public abstract class AbstractC {
    public abstract void method1Abs();
    public abstract void method2Abs();
}

接口定义

public interface Inter1 {
    void methodInter();
    void methodInter2();
}
​

使用

 public static void main(String[] args) {
        //匿名内部类可以应用在抽象类,接口 上面,抽象方法个数不要求
        exercise1(new AbstractC() {
            @Override
            public void method1Abs() {
                System.out.println("抽象类的抽象方法 执行了");
            }
​
            @Override
            public void method2Abs() {
​
            }
        });
​
        exercise2(new Inter1() {
            @Override
            public void methodInter() {
                System.out.println("");
            }
​
            @Override
            public void methodInter2() {
​
            }
        });
    }
​
    public static void exercise1(AbstractC c) {
        c.method1Abs();
    }
​
    public static void exercise2(Inter1 inter1) {
        inter1.methodInter();
    }

2,lambda表达式

  • lambda表达式 只能应用在接口上面;而且只能有一个抽象方法

  • @FunctionalInterface 注解可用在接口上面的 表示此接口只有一个抽象方法 函数式接口

接口定义

public interface AbstractC2 {
    int method1(String str, int num);
}
​

使用

public static void main(String[] args) {
        //lambda表达式 只能应用在接口上面;而且只能有一个抽象方法
        //@FunctionalInterface用在接口上面的 表示此接口只有一个抽象方法  函数式接口
        exercise1((a, b) -> {
            //方法体
            return 10;
        });
    }
​
    public static void exercise1(AbstractC2 c2) {
        c2.method1("hello", 10);
    }

1.1.2. Set子接口

  • 集合元素是单值;Set 的集合元素是 无序而且不可重复的

HashSet 底层使用的是HashMap

LinkedHashSet 底层使用的是LinkedHashMap

TreeSet 底层是TreeMap

1,Set的特点及实现类

 /**
     * Set的特点及实现类
     */
    private static void method2() {
        //Set无序 不可重复 副产品
        //HashSet内部使用的是HashMap
        HashSet<String> set1 = new HashSet<>();
        set1.add("java1");
        set1.add("java1");
        set1.add("java2");
        set1.add("java3");
        set1.add("java4");
        System.out.println(set1);
        //  LinkedHashSet是HashSet的子类; 内部使用的是LinkedHashMap 维持元素的添加顺序
        Set<String> set2 = new LinkedHashSet<>();
        set2.add("java1");
        set2.add("java1");
        set2.add("java2");
        set2.add("java3");
        set2.add("java4");
        System.out.println("set2: " + set2);
        // TreeSet 内部使用的是TreeMap; 要求TreeSet的类型要么实现Comparable 要么在TreeSet构造中提供比较器
        Set<Student> set3 = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getId() - o2.getId();
            }
        });
        set3.add(new Student());
​
        //List存取有序 可以重复
        List<String> list = new ArrayList<>(32);
        list.add("java1");
        list.add("java1");
        list.add("java2");
        list.add("java3");
        list.add("java4");
        System.out.println(list);
    }

2,遍历方式

1.2.Map接口

  • 集合元素是双值,一对对象(两个) 才是一个集合元素 key-value 键值对;主键对象:值对象

  • Map集合 Key对象是不可重复的

1.2.1. Map接口方法

 /**
     * Map 常用方法1
     */
    private static void method1() {
        //泛型不指定 都当成Object来看;约束
        Map<Integer, String> map = new HashMap<>();
        //1001:"java1" 1个Map的集合元素
        // key1001 ->"java1"
        map.put(1001, "java1");
        map.put(1002, "java2");
        //如果Key对象已经存在了  使用新的value对象替换旧的valued对象
        map.put(1002, "java3");
        //根据Key对象获取value对象;如果没有此key对象 取出来的是null
        String value = map.get(1001);
        // 要对Value对象作非空校验 才能调用valued的方法
        System.out.println("value: " + value.length());
        System.out.println("size 集合大小: " + map.size());
        // containsKey是否包含指定的Key对象
        System.out.println("containsKey: " + map.containsKey(1002));
        System.out.println("containsValue: " + map.containsValue("java2"));
        //keySet方法 获取所有的Key对象
        Set<Integer> integers = map.keySet();
        System.out.println("keySet: " + integers);
        //values方法 获取所有的value对象
        Collection<String> values = map.values();
        System.out.println("values: " + values);
        //remove方法 根据指定Key对象 删除键值对
//        map.remove(1004);
        //remove方法 根据指定Key对象以及value对象 删除键值对
        map.remove(1002, "java3");
        System.out.println(map);
    }
/**
     * Map常用方法2
     */
    private static void method2() {
        Map<Integer, String> map1 = new HashMap<>();
        map1.put(1001, "java1");
        map1.put(1002, "java2");
        //使用新的value对象替换指定 Key对应的value对象
        //map1.replace(1002, "Python");
        map1.replace(1002, "java3", "JS");
        System.out.println(map1);
​
        Map<Integer, String> map2 = new HashMap<>();
        //添加指定Map集合所有键值对
        map2.putAll(map1);
        //清空集合
        map2.clear();
        System.out.println("是否是空集合: " + map2.isEmpty());
        System.out.println(map2);
    }

1.2.2. Map使用

 /**
     * Map的value也是集合类型
     */
    private static void method4() {
        Map<Integer, ShareBike[]> map1 = new HashMap<>();
        map1.put(1001, new ShareBike[3]);
        System.out.println(map1);
​
        Map<Integer, List<Student>> map2 = new HashMap<>();
        List<Student> list1 = new LinkedList<>();
        list1.add(new Student());
        list1.add(new Student());
        list1.add(new Student());
​
        List<Student> list2 = new ArrayList<>();
        list2.add(new Student());
        list2.add(new Student());
        list2.add(new Student());
​
        map2.put(101, list1);
        map2.put(102, list2);
        List<Student> students = map2.get(101);
        System.out.println(map2);
​
        Map<Integer, Map<Integer, Student>> map3 = new HashMap<>();
        Map<Integer, Student> sonMap1 = new HashMap<>();
        sonMap1.put(100001, new Student(100001, "stu1", 12));
        sonMap1.put(100002, new Student(100002, "stu2", 12));
        map3.put(101, sonMap1);
​
        Map<Integer, Student> integerStudentMap = map3.get(101);
    }
​
    /**
     * Map的Key类型 必须具有唯一性
     */
    private static void method3() {
        //Key:Integer  Value :ShareBike
        //Integer String 唯一性
        Map<Integer, ShareBike> map = new HashMap<>();
        map.put(1001, new ShareBike(1001, 1, null));
        map.put(1002, new ShareBike(1002, 1, null));
        //
        ShareBike shareBike = map.get(1001);
        System.out.println(shareBike);
    }

1.2.3. Map的遍历

/**
     * Map的遍历方式
     */
    private static void method5() {
        Map<Integer, ShareBike> map = new HashMap<>();
        map.put(1001, new ShareBike(1001, 1, null));
        map.put(1002, new ShareBike(1002, 1, null));
        map.put(1003, new ShareBike(1003, 1, null));
        //1, 遍历方式
        Set<Integer> integers = map.keySet();
        for (Integer key : integers) {
            System.out.println(key + "=" + map.get(key));
        }
        System.out.println("=====================");
        //2, forEach遍历
       /* map.forEach(new BiConsumer<Integer, ShareBike>() {
            @Override
            public void accept(Integer integer, ShareBike shareBike) {
                System.out.println(integer + "=" + shareBike);
            }
        });*/
        map.forEach((k, v) -> {
            System.out.println(k + "=" + v);
        });
        System.out.println("++++++++++++++++++");
        //3, Node  Entry
        Set<Map.Entry<Integer, ShareBike>> entries = map.entrySet();
        /*entries.forEach(new Consumer<Map.Entry<Integer, ShareBike>>() {
            @Override
            public void accept(Map.Entry<Integer, ShareBike> entry) {
                System.out.println(entry.getKey() + "=" + entry.getValue());
            }
        });*/
        entries.forEach((entry) -> {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        });
    }

1.2.4. Map的实现类

1.2.4.1. HashMap
  • HashMap 哈希值 哈希算法:数据压缩算法;把无限范围内的数据 映射到有限范围内;抽屉原理,10个苹果需要放到 9个抽屉中 2个苹果放入到一个抽屉中了 这就是哈希冲突 哈希冲突解决不了 只能尽量减少 ;

  • HashMap 底层哈希表( JDK7之前 数组+单向链表 JD8之后加入了红黑树) 哈希表(数组+单向链表+红黑树)

  • 结合数组+链表的优点 , HashMap的查询和删除 性能都比较高

  • 引入红黑树的目的是为了解决链表查询性能过低的

static class Node<K,V> implements Map.Entry<K,V> {
    //用于存储key对象的哈希值
        final int hash;
    //用于存储key对象
        final K key;
    //用于存储value对象
        V value;
    //指向下一个节点
        Node<K,V> next;
​
        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
}

1,put源码实现

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        //
        Node[] tab;
        Node<K, V> p;
        int n, i;
        if ((tab = table) == null || (n = tab.length) == 0) {
            //第一次对数组初始化 ,对数组扩容
            tab = resize();
            //n Node数组的长度
            n = tab.length;
        }
        // (n - 1) & hash 等价于 hash % n 前提条件n必须是2的指数值
        if ((p = tab[i = (n - 1) & hash]) == null) {
            //新建Node对象 给数组元素赋值
            tab[i] = newNode(hash, key, value, null);
        } else {
            //
            Node<K, V> e;
            K k;
            //判断是否已经存在此Key对象
            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) {
                e = p;
                //判断后面是否是一颗红黑树
            } else if (p instanceof TreeNode) {
                e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);
            } else {
                //
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        //新节点 链接到最后
                        p.next = newNode(hash, key, value, null);
                        //判断 当前链表是否要进行 树化 转换为红黑树
                        if (binCount >= TREEIFY_THRESHOLD - 1) {
                            treeifyBin(tab, hash);
                        }
                        break;
                    }
                    //判断链表中每一个节点Key对象 是否与传入的Key对象相等 如果相等 本次是替换不是新增
                    if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
                        break;
                    }
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null) {
                    //value 对象的替换
                    e.value = value;
                }
                afterNodeAccess(e);
                return oldValue;
            }
        }
        //集合修改次数
        ++modCount;
        //元素个数 大于 临界值
        if (++size > threshold) {
            //扩容
            resize();
        }
        afterNodeInsertion(evict);
        return null;
    }

2,get源码实现

 final Node<K, V> getNode(int hash, Object key) {
        Node<K, V>[] tab;
        Node<K, V> first, e;
        int n;
        K k;
        if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) {
            //判断第一个元素是否是要找的节点对象
            if (first.hash == hash && ((k = first.key) == key || (key != null && key.equals(k)))) {
                return first;
            }
            //判断下一个节点是否不为null
            if ((e = first.next) != null) {
                //在红黑树中查询节点
                if (first instanceof TreeNode) {
                    return ((TreeNode<K, V>) first).getTreeNode(hash, key);
                }
                //在链表中进行查找
                do {
                    if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
                        return e;
                    }
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

3,使用注意

  • 无参构造中 并未初始化数组 在第一次put的时候初始化数组长度为16 以后每次2倍扩容

  • 推荐使用有参构造 为了避免多次 无效扩容;给预估值

/**
     * HashMap的构造方式
     */
    private static void method6() {
        // 无参构造中 并未初始化数组  在第一次put的时候初始化数组长度为16 以后每次2倍扩容
        HashMap<String, String> map = new HashMap<>();
        //推荐使用有参构造 为了避免多次 无效扩容 ; 31->32 32->32 60->64
        HashMap<String, String> map2 = new HashMap<>(31);
        map.get("a");
        map.put("aa", "java1");
        map.put("aa", "java2");
        String value = map.get("aa");
    }

1.2.4.2. LinkedHashMap
  • LinkedHashMap是HashMap的子类;

  • LinkedHashMap 哈希表的基础上 加入了双向链表,为了维持元素的插入顺序

 private static void method7() {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("java", "java1");
        hashMap.put("js", "java2");
        hashMap.put("python", "java3");
        System.out.println(hashMap);
​
​
        //LinkedHashMap 哈希表的基础上 加入了双向链表,为了维持元素的插入顺序
        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("java", "java1");
        linkedHashMap.put("js", "java2");
        linkedHashMap.put("python", "java3");
        System.out.println(linkedHashMap);
    }
1.2.4.3 TreeMap
  • TreeMap底层就是 红黑树 二叉排序树 根据Key对象比较大小进行排序的

  • TreeMap的Key类型要么实现 Comparable接口,要么在TreeMap构造中提供比较器

private static void method8() {
        TreeMap<Student, String> treeMap4 = new TreeMap<>((o1, o2) -> {
            return o1.getId() - o2.getId();
        });
        treeMap4.put(new Student(101, "t1", 12), "java1");
        treeMap4.put(new Student(102, "t2", 12), "java2");
        treeMap4.put(new Student(101, "t3", 19), "java3");
        System.out.println(treeMap4);
​
        //底层就是 红黑树 二叉排序树 根据Key对象比较大小进行排序的
        TreeMap<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(98, "java1");
        treeMap.put(198, "java2");
        treeMap.put(10, "java3");
        treeMap.put(220, "java3");
        treeMap.put(2, "java4");
        System.out.println(treeMap);
        //TreeMap的Key类型要么实现 Comparable接口,要么在TreeMap构造中提供比较器
        /*TreeMap<Student, String> treeMap2 = new TreeMap<>();
        treeMap2.put(new Student(), "java");*/
        TreeMap<Student, String> treeMap3 = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getId() - o2.getId();
            }
        });
        treeMap3.put(new Student(), "java1");
        System.out.println(treeMap3);
    }
1.2.4.4. Hashtable
  • Hashtable是线程安全的Map,HashMap线程不安全 不能在多线程中使用

  • 多线程项目推荐使用 ConcurrentHashMap,性能较高

 public static void main(String[] args) {
        ConcurrentHashMap<Integer, String> concurrentHashMap = new ConcurrentHashMap<>();
        Hashtable<Integer, String> hashtable = new Hashtable<>();
    }

1.3.工具方法

1,of 静态方法

     /**
     * of静态方法
     */
    private static void method1() {
        //不可变的集合对象
        List<Integer> integerList = List.of(66, 88, 9, 199, 10, 2, 1);
        List<String> stringList = List.of("java1", "java2");
        System.out.println(integerList);
​
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.addAll(integerList);
        arrayList.add(3);
        System.out.println(arrayList);
​
        //不可变的集合对象
        Set<String> stringSet = Set.of("java", "JS", "python");
        Map<Integer, String> map = Map.of(12, "java1", 34, "java2", 89, "java3");
        System.out.println(map);
    }
   private static void method2() {
        //也是 不可更改的 集合对象
        List<String> strings = Arrays.asList("java1", "java2");
        System.out.println(strings);
    }

2,Collections方法

​
    /**
     * Collections方法1
     */
    private static void method3() {
        List<Student> students = new ArrayList<>();
        students.add(new Student(901, 99));
        students.add(new Student(301, 89));
        students.add(new Student(909, 100));
        students.add(new Student(201, 19));
        //List Set 排序 可比较大小
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return (o1.getScore() - o2.getScore());
            }
        });
        Student max = Collections.max(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });
        Student min = Collections.min(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });
        System.out.println(students);
        System.out.println(max);
        System.out.println(min);
    }

 /**
     * Collections方法2
     */
    private static void method5() {
        List<Integer> list = List.of(45, 66, 88, 19, 100, 1, 4, 5);
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.addAll(list);
        Collections.sort(arrayList);
        Integer max = Collections.max(arrayList);
        Integer min = Collections.min(arrayList);
        System.out.println(arrayList);
        System.out.println(max);
        System.out.println(min);
        //倒置  颠倒顺序
        Collections.reverse(arrayList);
        //重新洗牌 顺序打乱
        Collections.shuffle(arrayList);
        System.out.println(arrayList);
        //返回对应的 空集合 也是不可更改的;
        List<Object> objects = Collections.emptyList();
        Set<Object> objects1 = Collections.emptySet();
        Map<Object, Object> map = Collections.emptyMap();
    }

3,Stream流

  • 丰富了对Collection集合的操作

 /**
     * Stream 方法使用
     */
    private static void method6() {
        List<Student> students = new ArrayList<>();
        students.add(new Student(1001, 99));
        students.add(new Student(1002, 89));
        students.add(new Student(1003, 50));
        students.add(new Student(1004, 19));
        students.add(new Student(1005, 39));
        students.add(new Student(1006, 29));
        students.add(new Student(1007, 79));
        //1,生成Stream流对象
        Stream<Student> stream1 = students.stream();
        /*
        Stream流对象是一次性的,只能被操作一次
         中间操作 方法 看方法的返回值 只要返回值是Stream类型
         ***惰性方法 如果不碰到终止操作方法 不会执行
         ***filter 过滤
         ***map 映射 把流中的数据 经过相同的规则 映射为新的值;
         ***sorted() 排序
         ***limit(3)
         ***peek(); 偷窥
         终止操作 方法 只要返回值不是Stream类型
         ***collect() 收集
         ***count() 统计流个数
         ***reduce() 合并 合为一个数据
         ***max();
         ***min();
         */
        //filter过滤
        Stream<Student> stream2 = stream1.filter(new Predicate<Student>() {
            //返回值为true 表示要保留
            @Override
            public boolean test(Student student) {
                return student.getScore() >= 60;
            }
        });
        Stream<Student> stream3 = stream2.map(new Function<Student, Student>() {
            @Override
            public Student apply(Student student) {
                student.setScore(student.getScore() - 2);
                return student;
            }
        });
        Stream<Student> stream4 = stream3.sorted(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });
        Stream<Student> stream5 = stream4.limit(3);
        Stream<Student> stream6 = stream5.peek(new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                System.out.println(student);
            }
        });
        Optional<Student> max = stream6.min(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });
        System.out.println("=============");
        System.out.println(max.get());
​
        /*Optional<Student> reduce = stream6.reduce(new BinaryOperator<Student>() {
            @Override
            public Student apply(Student o1, Student o2) {
                o1.setScore(o1.getScore() + o2.getScore());
                return o1;
            }
        });
        System.out.println(reduce.get().getScore());*/
//        System.out.println(stream6.count());
       /* List<Student> collect = stream6.collect(Collectors.toList());
        System.out.println(collect);*/
​
​
​
       /* Iterator<Student> iterator = students.iterator();
        while (iterator.hasNext()) {
            Student student = iterator.next();
            if (student.getScore() < 60) {
                iterator.remove();
            }
        }
        System.out.println(students);
        //所有学生成绩都减去2
        for (Student stu : students) {
            stu.setScore(stu.getScore() - 2);
        }
        System.out.println(students);*/
    }

简化写法

 /**
     * Stream方法 简化写法
     */
    private static void method7() {
        List<Student> students = new ArrayList<>();
        students.add(new Student(1001, 99));
        students.add(new Student(1002, 89));
        students.add(new Student(1003, 50));
        students.add(new Student(1004, 19));
        students.add(new Student(1005, 39));
        students.add(new Student(1006, 29));
        students.add(new Student(1007, 79));
        System.out.println(students.stream().filter((s) -> {
            return s.getScore() >= 60;
        }).map((s) -> {
            s.setScore(s.getScore() - 2);
            return s;
        }).sorted((o1, o2) -> {
            return o1.getScore() - o2.getScore();
        }).limit(3).max((o1, o2) -> {
            return o1.getScore() - o2.getScore();
        }).get());
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值