Java第十四课_集合和lambda表达式

1.List

  • ArrayList

        public static void main(String[] args) {
            // JDK8.0对集合进行有优化
            // Collection 表示一组对象,这些对象也称为 collection 的元素。
            //  | List : 元素可以重复 ; 保证插入顺序和取出顺序一致
            //      | ArrayList :
            //                    数组结构
            //                    查询快,增删效率略低
            //                    线程不安全的
            //                    容量不够时,按自身的50%进行扩容    10 ---> 15 ---> 22
            //                  JDK8.0与7.0中 ArrayList的区别 ?
            //                  JDK7.0 : 在使用空参构造器创建ArrayList对象时,直接开辟了 10个 空间,用来存储元素
            //                  JDK8.0 在使用 空参构造器创建ArrayList对象时,先创建的空数组,在使用 add函数添加第一个元素时,才开辟10个的空间
            //      | Vector :
            //                    数组结构
            //                    线程安全
            //                    容量不够时,按自身的100%进行扩容    10  ---> 20 ---> 40
            //      | LinkedList :
            //                   链表结构(双向链表) : 冰糖葫芦
            //                   线程不安全
            //                   查询慢,增删快
            //  | Set : 元素唯一 ; 不保证插入顺序和取出顺序一致
            //      | HashSet :
            //                  哈希表结构
            //                  线程不安全
            //      | Hashtable :
            //                  哈希表结构
            //                  线程安全
            //      | TreeSet :
            //                  二叉树结构
            //                  线程不安全
            //                  会对元素进行排序
            // 注意 : 集合中的 contains 函数  , remove 函数 以及 indexOf , lastIndexOf 函数会根据集合中的元素的equals函数进行判断
    
            Collection<Integer> collection = new ArrayList<>();
            collection.add(111);
            collection.add(222);
            collection.add(333);
            collection.add(444);
            collection.add(555);
            // Consumer : 消费型接口 : 有来无回          void accept(T t);
            // Supplier : 供给型接口 :                  T get();
            // Function : 函数型接口 : 有来有往           R apply(T t);
            // Predicate : 断言型接口 :   条件           boolean test(T t);
    
            // 外部迭代 : 自己写循环
            // 内部迭代 : 循环在底层,如下
            collection.stream().forEach(new Consumer<Integer>(){// Consumer : 消费型接口
                public void accept(Integer element){
                    System.out.println("element = " + element);
                }
            });
    
            // collection.stream()  串行流
            // collection.parallelStream() 并行流
            collection.parallelStream().forEach(new Consumer<Integer>(){
                public void accept(Integer element){
                    System.out.println("parallelStream : element = " + element);
                }
            });
    
            // default boolean	removeIf​(Predicate<? super E> filter)
            //      如果存在就删除
            collection.removeIf(new Predicate<Integer>() {// Predicate : 断言型接口
                @Override
                public boolean test(Integer integer) {
                    return integer > 500;
                }
            });
            System.out.println("collection = " + collection);
    
            // default Spliterator<E>	spliterator()
        }
    
    public class User {
    
        private String name;
        private Integer age;
    
        public User() {
        }
    
        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            User user = (User) o;
            return Objects.equals(name, user.name) &&
                    Objects.equals(age, user.age);
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    @FunctionalInterface// 函数式接口的注解
    public interface IA {
        // 函数式接口 : 抽象函数的个数 有且只有一个;
        boolean test();
        // boolean test2();
    
        static void m2(){// 非抽象函数正常
    
        }
    
        default int m3(){
            return 0;
        }
    }
    
  • ArrayList常用操作

        public static void main(String[] args) {
    
            List<User> list = new ArrayList<>();
            list.add(new User("lisi1", 20));
            list.add(new User("lisi2", 20));
            list.add(new User("lisi3", 20));
            list.add(new User("lisi4", 20));
            list.add(new User("lisi5", 20));
    
            //  void add(int index, E element)
            //           在列表的指定位置插入指定元素(可选操作)。
            list.add(2, new User("xiaoming", 18));
    
            //  E get(int index)
            //           返回列表中指定位置的元素。
            User user = list.get(2);
            System.out.println("user = " + user);
    
            //  int indexOf(Object o)
            //           返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
            // int lastIndexOf(Object o)
            //           返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
            System.out.println("index = " + list.indexOf(new User("xiaoming", 18)));
    
            //  E remove(int index) 获取并移除
            //           移除列表中指定位置的元素(可选操作)。
            System.out.println("remove = " + list.remove(2));
    
            //  E set(int index, E element)
            //           用指定元素替换列表中指定位置的元素(可选操作), 并返回被替换元素。
            System.out.println("setUser = " + list.set(2, new User("laowang", 22)));
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    
            //  List<E> subList(int fromIndex, int toIndex)
            //           返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
            List<User> list1 = list.subList(1, 5);
            for (User user1 : list1) {
                System.out.println("user1 = " + user1);
            }
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            list.forEach(System.out::println);
    
    
    
            // static <E> List<E>	of​(E... elements) 1.9开始的功能. 提供的是不可变列表,不能使用增删功能. 但可以修改元素内容,或查询
            //     UnsupportedOperationException : 不支持的操作异常
            // static <E> List<E>	of​(E e1, E e2)
    
            // List<User> list2 = List.of(new User("zs1", 20), new User("zs2", 20), new User("zs2", 20), new User("zs2", 20));
            // list2.forEach(System.out::println);
            // // list2.remove(new User("zs1", 20));
            // System.out.println("list2 = " + list2);
            //
            // int zs1 = list2.indexOf(new User("zs1", 20));
            // System.out.println("zs1 = " + zs1);
            // User user1 = list2.get(zs1);
            // user1.setName("张三");
            //
            // // list2.add(new User());// UnsupportedOperationException
            //
            // System.out.println("list2 = " + list2);
            //
            // // default void	sort​(Comparator<? super E> c)
            // // default Spliterator<E>	spliterator()
            //
            // // List特有的遍历方式 : 普通循环
            //
            // for (int i = 0, size = list2.size(); i < size; ++i) {
            //     User user2 = list2.get(i);
            //     System.out.println("user2 = " + user2);
            // }
        }
    
  • ListIterator迭代器

        public static void main(String[] args) {
            // ListIterator<E> listIterator()
            //           返回此列表元素的列表迭代器(按适当顺序)。
            //  ListIterator<E> listIterator(int index)
            //           返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
    
            // ConcurrentModificationException : 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
            //      原因 : 在读取列表的同时,向列表中添加元素
            List<String> list = new ArrayList<>();
    
            list.add("aaa");
            list.add("bbb");
            list.add("ccc");
            list.add("ddd");
            list.add(null);
    
            for (ListIterator<String> listIterator = list.listIterator(); listIterator.hasNext(); ) {
                String s = listIterator.next();
                if ("bbb".equals(s)) {
                    listIterator.add("eee");// ListIterator.add()可以在读取列表的同时,向列表中添加元素
                }
            }
            list.forEach(System.out::println);
            System.out.println("---------------------------------");
    
            //倒序遍历
            for (ListIterator<String> listIterator = list.listIterator(list.size()); listIterator.hasPrevious(); ) {
                String previous = listIterator.previous();
                System.out.println("previous = " + previous);
                if ("ccc".equals(previous)) {
                    listIterator.set("zzz");
                }
            }
            System.out.println("list = " + list);
        }
    
  • Vector

        public static void main(String[] args) {
    
            // Vector :
            Vector<String> vector = new Vector<>();
            //  int capacity()  理论容量
            //           返回此向量的当前容量。
            //  int size()  实际容量
            //           返回此向量中的组件数
            System.out.println("vector.capacity() = " + vector.capacity());
            System.out.println("vector.size() = " + vector.size());
    
            vector.add("aaa");
            vector.add("bbb");
            vector.add("ccc");
            vector.add("ddd");
            vector.add("eee");
            vector.addAll(vector);
            vector.add("zzz");
    
            //  void trimToSize()
            //           将此 ArrayList 实例的容量调整为列表的当前大小。
            vector.trimToSize();
            System.out.println("vector.capacity() = " + vector.capacity());
            System.out.println("vector.size() = " + vector.size());
    
            // 遍历/迭代
            // Enumeration : 古老版本的迭代器 ,
            // Enumeration enumeration = vector.elements();
            for (Enumeration<String> enumeration = vector.elements(); enumeration.hasMoreElements(); ) {
                String s = enumeration.nextElement();
                System.out.println("s = " + s);
            }
        }
    
  • LinkedList

        public static void main(String[] args) {
    
            LinkedList<String> linkedList = new LinkedList<>();
    
            linkedList.add("111");
            linkedList.add("222");
            linkedList.add("333");
            linkedList.add("444");
            linkedList.add("555");
            // void addFirst(E e)
            //           将指定元素插入此列表的开头。
            //  void addLast(E e)
            //           将指定元素添加到此列表的结尾。
            System.out.println("linkedList = " + linkedList);
            linkedList.addFirst("000");
            linkedList.addLast("666");
            System.out.println("linkedList = " + linkedList);
    
            // linkedList.clear();
            // 如果列表为 空 ,则产生 NoSuchElementException
            // E element()
            //           获取但不移除此列表的头(第一个元素)。
            // System.out.println("linkedList.element() = " + linkedList.element());
            // E getFirst()
            //           返回此列表的第一个元素。
            // System.out.println("linkedList.getFirst() = " + linkedList.getFirst());
            //  E getLast()
            //           返回此列表的最后一个元素。
            // System.out.println("linkedList.getLast() = " + linkedList.getLast());
    
            //  boolean offer(E e)
            //           将指定元素添加到此列表的末尾(最后一个元素)。
            //  boolean offerFirst(E e)
            //           在此列表的开头插入指定的元素。
            //  boolean offerLast(E e)
            //           在此列表末尾插入指定的元素。
            System.out.println("linkedList.offer(\"-1\") = " + linkedList.offer("-1"));
            System.out.println("linkedList.offerFirst(\"-2\") = " + linkedList.offerFirst("-2"));
            System.out.println("linkedList.offerLast(\"777\") = " + linkedList.offerLast("777"));
            System.out.println("linkedList = " + linkedList);
    
    
            //  E peek()
            //           获取但不移除此列表的头(第一个元素)。
            //  E peekFirst()
            //           获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
            //  E peekLast()
            //           获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
            // linkedList.clear();
            System.out.println("linkedList.peek() = " + linkedList.peek());
            System.out.println("linkedList.peekFirst() = " + linkedList.peekFirst());
            System.out.println("linkedList.peekLast() = " + linkedList.peekLast());
            System.out.println("linkedList = " + linkedList);
            // linkedList.clear();
            //  E poll()
            //           获取并移除此列表的头(第一个元素)
            //  E pollFirst()
            //           获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
            //  E pollLast()
            //           获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
            System.out.println("linkedList.poll() = " + linkedList.poll());
            System.out.println("linkedList.pollFirst() = " + linkedList.pollFirst());
            System.out.println("linkedList.pollLast() = " + linkedList.pollLast());
            System.out.println("linkedList = " + linkedList);
    
            //  E removeFirst()
            //           移除并返回此列表的第一个元素。
            //  E removeLast()
            //           移除并返回此列表的最后一个元素。
            System.out.println("linkedList.removeFirst() = " + linkedList.removeFirst());
            System.out.println("linkedList.removeLast() = " + linkedList.removeLast());
            System.out.println("linkedList = " + linkedList);
    
            // 堆栈 : 弹夹 :        先进后出
            // 队列 :              先进先出
            //  void push(E e)
            //           将元素推入此列表所表示的堆栈。
            linkedList.push("aaa");
            System.out.println("linkedList = " + linkedList);
            //  E pop()
            //           从此列表所表示的堆栈处弹出一个元素。
            System.out.println("linkedList.pop() = " + linkedList.pop());
        }
    

2.Set

  • HashSet和LinkedHashSet

        public static void main(String[] args) {
            //  | Set : 元素唯一 ; 不保证插入顺序和取出顺序一致
            //      | HashSet :
            //                  哈希表结构
            //                  线程不安全
            //              唯一原则 :
            //                  先使用 元素 的 hashCode函数进行比较 , 如果不同,直接存储;
            //                             如果相同,则调用元素的 equals() 函数进行判断,
            //                              如果不同直接存储,相同舍弃
            //          | LinkedHashSet : 哈希表 + 链表
            //                  保证插入顺序和取出顺序一致
            //      | TreeSet :
            //                  二叉树结构
            //                  线程不安全
            //                  会对元素进行排序
    
            // LinkedHashSet
            LinkedHashSet<User> linkedHashSet = new LinkedHashSet<>();
            linkedHashSet.add(new User("lisi1",120));
            linkedHashSet.add(new User("lisi2",20));
            linkedHashSet.add(new User("lisi3",23));
            linkedHashSet.add(new User("lisi4",26));
            linkedHashSet.add(new User("lisi5",18));
            linkedHashSet.add(new User("lisi5",18));
            linkedHashSet.forEach(System.out::println);
            System.out.println("------------------------------------");
    
            // HashSet
            HashSet<String> hashSet = new HashSet<>();
            hashSet.add("JavaSE1");
            hashSet.add("MySQL2");
            hashSet.add("JDBC3");
            hashSet.add("html4");
            hashSet.add("css5");
            hashSet.add("JavaScript6");
            hashSet.add("JavaEE8");
            hashSet.add("JSP9");
            hashSet.add("JSP9");
            hashSet.add("JSP9");
            hashSet.forEach(System.out::println);
            System.out.println("------------------------------------");
    
            // 重写hashCode函数后,该函数返回的哈希值是由 哈希算法得到的,不再是堆内存分配的地址值
            HashSet<User> hashSet1 = new HashSet<>();
            hashSet1.add(new User("lisi", 20));
            User user = new User("lisi", 22);
            System.out.println("user.hashCode() = " + user.hashCode());
        }
    
    public class User {
    
        private String name;
        private Integer age;
    
        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public boolean equals(Object o) {
            // System.out.println(this + "      :::          " + o);
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            User user = (User) o;
            return Objects.equals(name, user.name) &&
                    Objects.equals(age, user.age);
        }
    
        @Override
        public int hashCode() {
            // System.out.println("this.hashCode : " + this);
            return Objects.hash(name, age);
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
  • TreeSet

        public static void main(String[] args) {
            // TreeSet : 会对元素自动排序
            //      1.自然排序 : 要求 元素类型实现 Comparable<T> 接口
            //      2.定制排序/自定义排序 : 创建TreeSet对象时需要提供 比较器对象(Comparator<T>)
            //  注意 : 两种排序同时存在,优先按 定制排序进行排序
            TreeSet<String> treeSet = new TreeSet<>();
            treeSet.add("html");
            treeSet.add("css");
            treeSet.add("js");
            treeSet.add("JQuery");
            treeSet.add("maven");
            treeSet.add("git");
            treeSet.add("svn");
            treeSet.forEach(System.out::println);
            System.out.println("------------------------------------");
    
            //      1.自然排序, 在Student类中实现Comparable接口
            TreeSet<Student> treeSet1 = new TreeSet<>();
            treeSet1.add(new Student("lisi", 22));
            treeSet1.add(new Student("lisi", 20));
            treeSet1.add(new Student("zs", 20));
            treeSet1.add(new Student("king", 18));
            treeSet1.add(new Student("kitty", 22));
            treeSet1.forEach(System.out::println);
            System.out.println("------------------------------------");
    
            //      2.定制排序
            // a.编写比较器的子类 NameComparator
            // b.创建比较器对象
            NameComparator nameComparator = new NameComparator();
            // c.创建TreeSet的对象,并将比较器对象传递给 TreeSet
            TreeSet<Student> treeSet2 = new TreeSet<>(nameComparator);
            treeSet2.add(new Student("lisi", 22));
            treeSet2.add(new Student("lisi", 20));
            treeSet2.add(new Student("zs", 20));
            treeSet2.add(new Student("king", 18));
            treeSet2.add(new Student("kitty", 22));
            treeSet2.forEach(System.out::println);
        }
    
    public class Student implements Comparable<Student>{
    
        private String name;
        private Integer age;
    
        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        @Override
        public int compareTo(Student o1) {
            // 名字升序 年龄降序
            int num = name.compareTo(o1.name);
            if (num == 0) {
                return - age.compareTo(o1.age);
            }
            return num;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    public class NameComparator  implements Comparator<Student> {
        @Override
        public int compare(Student o1, Student o2) {
            // 年龄升序名字降序
            int num = o1.getAge().compareTo(o2.getAge());
            if (num == 0) {
                return -o1.getName().compareTo(o2.getName());
            }
            return num;
        }
    }
    

3.lambda表达式和可变参数列表

  • lambda表达式

        public static void main(String[] args) {
            //lambda表达式
    
            //原版
            TreeSet<Student> treeSet1 = new TreeSet<>(new Comparator<Student>(){
                @Override
                public int compare(Student o1, Student o2) {
                    // 年龄升序名字降序
                    int num = o1.getAge().compareTo(o2.getAge());
                    if (num == 0) {
                        return -o1.getName().compareTo(o2.getName());
                    }
                    return num;
                }
            });
            treeSet1.add(new Student("lisi", 20));
            treeSet1.add(new Student("zs", 12));
            treeSet1.add(new Student("zhaoliu", 18));
            treeSet1.add(new Student("tianqi", 25));
            treeSet1.add(new Student("lisng", 25));
            treeSet1.forEach(System.out::println);
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~lambda表达式 : JDK8.0开始使用~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    
            //修正版01
            //      new TreeSet<>后面必然是Comparator<Student>的实现, 内容必然是重写public int compare()函数, 全部省略
            TreeSet<Student> treeSet2 = new TreeSet<>(
                    (Student o1, Student o2) -> {
                        // 年龄升序名字降序
                        int num = o1.getAge().compareTo(o2.getAge());
                        if (num == 0) {
                            return -o1.getName().compareTo(o2.getName());
                        }
                        return num;
                    }
            );
            treeSet2.add(new Student("lisi", 20));
            treeSet2.add(new Student("zs", 12));
            treeSet2.add(new Student("zhaoliu", 18));
            treeSet2.add(new Student("tianqi", 25));
            treeSet2.add(new Student("lisng", 25));
            treeSet2.forEach(System.out::println);
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~lambda表达式 : JDK8.0开始使用~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    
            //修正版02
            //      lambda表达式中,形参的类型是可以省略的.
            TreeSet<Student> treeSet3 = new TreeSet<>(
                    (o1, o2) -> {
                        // 年龄升序名字降序
                        int num = o1.getAge().compareTo(o2.getAge());
                        if (num == 0) {
                            return -o1.getName().compareTo(o2.getName());
                        }
                        return num;
                    }
            );
            treeSet3.add(new Student("lisi", 20));
            treeSet3.add(new Student("zs", 12));
            treeSet3.add(new Student("zhaoliu", 18));
            treeSet3.add(new Student("tianqi", 25));
            treeSet3.add(new Student("lisng", 25));
    
            //输出语句原版
            treeSet3.forEach(new Consumer<Student>(){
                @Override
                public void accept(Student student) {
                    System.out.println(student);
                }
            });
            System.out.println("-----------------------------------------");
    
            //输出语句修正版01 去掉重写
            treeSet3.forEach(
                    (student) -> {
                        System.out.println(student);
                    }
            );
            System.out.println("-----------------------------------------");
    
            //输出语句修正版02
            //     当形参只有一个参数时 , 小括号可以省略不写.
            //     当方法体只有一条语句时 , 大括号可以省略不写 , 同时去掉末尾分号 , 如果是return语句,return也要省略
            treeSet3.forEach(student -> System.out.println(student));
            System.out.println("-----------------------------------------");
    
            //输出语句修正版03
            // 当 lambda 表达式的 函数体已经有函数实现时,可以使用 函数引用
            //          对象::函数名
            //          形参刚好是被调用函数的参数
            treeSet3.forEach(System.out::println);
            System.out.println("-----------------------------------------");
            //等同于:
            PrintStream out = System.out;
            treeSet3.forEach(out::println);
        }
    
  • ...可变参数列表

        public static void main(String[] args) {
            // 可变参数列表 :
            // 1.本质就是数组
            // 2.如果存在精确匹配,优先执行精确匹配
            // 3.可变参数列表必须位于所有参数的后面
    
            int[] arr = {23, 12, 15};
            print(arr);
            print(25);
            print(1521, 3306);
            print(1521, 3306, 9527, 143);
    
        }
    
        public static void print(String s, int... arr) {        // int... arr 可变参数列表
    
        }
        public static void print(int ... arr){
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
    
        public static void print(int i){
            System.out.println("i1 = " + i);
        }
    
        public static void print(int i,int j){
            System.out.println("i2 = " + i + " , j2 = " + j);
        }
    
posted @ 2023-12-20 22:17  张心野  阅读(48)  评论(0)    收藏  举报