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); }