Collection
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 Collection<String> c = new ArrayList <>(); Collection<String> set = new HashSet <>(); boolean b1 = c.add("A" ); boolean b2 = c.add("B" ); boolean b3 = c.add("A" ); c.addAll(List.of("X" , "Y" )); int n = c.size(); boolean empty = c.isEmpty(); boolean has = c.contains("A" ); boolean all = c.containsAll(List.of("A" ,"B" )); boolean r1 = c.remove("A" ); Collection<Integer> nums = new ArrayList <>(); nums.add(0 ); nums.add(1 ); nums.remove(0 ); ((List<Integer>)nums).remove(0 ); c.removeAll(List.of("A" ,"B" )); c.retainAll(List.of("X" )); c.clear(); c.removeIf(s -> s == null ); c.removeIf(s -> s.startsWith("A" )); Iterator<String> it = c.iterator(); while (it.hasNext()) { String s = it.next(); if (s.length() > 3 ) it.remove(); } for (String s : c) { ... } Object[] a1 = c.toArray(); String[] a2 = c.toArray(new String [0 ]); c.stream().filter(...).forEach(...);
迭代器以及遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 Collection<String> c = new ArrayList <>(List.of("A" , "BB" , "CCC" , "DDDD" )); for (String s : c) { System.out.println(s); } int i = 0 ;for (String s : c) { System.out.println(i++ + ":" + s); }c.forEach(s -> System.out.println(s)); c.forEach(System.out::println); c.forEach((String s) -> { System.out.println(s); }); c.forEach(s -> { if (s.length() > 2 ) System.out.println(s); }); StringBuilder sb = new StringBuilder ();c.forEach(sb::append); c.removeIf(s -> s.length() > 2 ); Iterator<String> it = c.iterator(); while (it.hasNext()) { String s = it.next(); if (s == null ) continue ; if (s.length() > 2 ) { it.remove(); } } ListIterator<String> lit = ((List<String>)c).listIterator(); while (lit.hasNext()) { int idx = lit.nextIndex(); String s = lit.next(); if (s.length() > 2 ) lit.remove(); else lit.add("X" ); } lit.hasPrevious(); lit.previous(); List<String> list = new ArrayList <>(c); for (int i = list.size() - 1 ; i >= 0 ; i--) { if (list.get(i).length() > 2 ) list.remove(i); }
List集合
方法名
描述
void add(int index,E element)
在此集合中的指定位置插入指定的元素
E remove(int index)
删除指定索引处的元素,返回被删除的元素
E set(int index,E element)
修改指定索引处的元素,返回被修改的元素
E get(int index)
返回指定索引处的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 List<Integer> li = new ArrayList <>(); li.add(1 ); li.add(2 ); li.remove(1 ); ListIterator<String> it = list.listIterator(); while (it.hasNext()){ String str = it.next(); if ("bbb" .equals(str)){ it.add("qqq" ); } }
LinkedList
方法名
说明
public void addFirst(E e)
在该列表开头插入指定的元素
public void addLast(E e)
将指定的元素追加到此列表的末尾
public E getFirst()
返回此列表中的第一个元素
public E getLast()
返回此列表中的最后一个元素
public E removeFirst()
从此列表中删除并返回第一个元素
public E removeLast()
从此列表中删除并返回最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class MyLinkedListDemo4 { public static void main (String[] args) { LinkedList<String> list = new LinkedList <>(); list.add("aaa" ); list.add("bbb" ); list.add("ccc" ); } private static void method4 (LinkedList<String> list) { String first = list.removeFirst(); System.out.println(first); String last = list.removeLast(); System.out.println(last); System.out.println(list); } private static void method3 (LinkedList<String> list) { String first = list.getFirst(); String last = list.getLast(); System.out.println(first); System.out.println(last); } private static void method2 (LinkedList<String> list) { list.addLast("www" ); System.out.println(list); } private static void method1 (LinkedList<String> list) { list.addFirst("qqq" ); System.out.println(list); } }
泛型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 class Box <T> { private final T value; Box(T value) { this .value = value; } T get () { return value; } } @FunctionalInterface interface Converter <T, R> { R convert (T t) ; } class Utils { static <T> T first (List<T> list) { return list.get(0 ); } static <T extends Comparable <T>> T max (T a, T b) { return a.compareTo(b) >= 0 ? a : b; } } Box<String> box = new Box <>("hello" ); String s = box.get();Converter<String, Integer> len = String::length; Converter<String, Integer> len2 = str -> str.length(); Integer n = len.convert("java" );List<Integer> nums = List.of(1 , 2 , 3 ); Integer first = Utils.first(nums);Integer max = Utils.max(3 , 7 );class Ye {}class Fu extends Ye {}class Zi extends Fu {}ArrayList<Ye> list1 = new ArrayList <>(); ArrayList<Fu> list2 = new ArrayList <>(); ArrayList<Zi> list3 = new ArrayList <>(); method(list1); list1.add(new Ye ()); list1.add(new Fu ()); list1.add(new Zi ()); public static void method (ArrayList<Ye> list) {}double sum (List<? extends Number> list) { double total = 0 ; for (Number num : list) total += num.doubleValue(); return total; } sum(List.of(1 , 2 , 3 )); sum(List.of(1.5 , 2.5 )); void addInts (List<? super Integer> list) { list.add(1 ); Object o = list.get(0 ); } List<Number> numberList = new ArrayList <>(); addInts(numberList); addInts(new ArrayList <Object>()); static <T> void copy (List<? super T> dest, List<? extends T> src) { for (T t : src) dest.add(t); }
数据结构
栈结构:先进后出,后进先出
队列结构:先进先出,后进后出
数组结构:查询快、增删慢
链表结构:查询慢、增删快
二叉树
二叉树中,任意一个节点的度要小于等于2
节点:在树结构中,每一个元素称之为节点
度:每一个节点的子节点数量称之为度
二叉查找树
每一个节点上最多有两个子节点
左子树上所有节点的值都小于根节点的值
右子树上所有节点的值都大于根节点的值
添加节点规则:小的存左边,大的存右边,一样的不存
遍历:
前序遍历:当前节点,左子节点,右子结点
中序遍历:左子节点,当前节点,右子结点
后序遍历:左子节点,右子结点,当前节点
层序遍历:一层一层的去遍历
平衡二叉树
二叉树左右两个子树的高度差不超过1
任意节点的左右两个子树都是一颗平衡二叉树
左旋:就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
右旋:就是将根节点的左侧往右拉,左子节点变成了新的父节点,并把多余的右子节点出让,给已经降级根节点当左子节点
平衡二叉树旋转的四种情况
左左
左左:当根节点左子树的左子树有节点插入,导致二叉树不平衡
如何旋转:直接对整体进行右旋即可
左右
左右:当根节点左子树的右子树有节点插入,导致二叉树不平衡
如何旋转:先在左子树对应的节点位置进行左旋,在对整体进行右旋
右右
右右:当根节点右子树的右子树有节点插入,导致二叉树不平衡
如何旋转:直接对整体进行左旋即可
右左
右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡
如何旋转:先在右子树对应的节点位置进行右旋,在对整体进行左旋
红黑树
平衡二叉B树
每一个节点可以是红或者黑
红黑树不是高度平衡的,它的平衡是通过“自己的红黑规则”进行实现的
红黑规则
每一个节点或是红色的,或者是黑色的
根节点必须是黑色
红黑树中,所有空指针(null)在逻辑上均被视为指向一个黑色的虚拟叶子节点(NIL/哨兵节点),它不存数据,仅作为路径终点统一黑高计算基准。
如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
红黑树添加节点的默认颜色:添加节点时,默认为红色,效率高
保持红黑规则:
根节点位置:直接变为黑色
非根节点位置
父节点为黑色
父节点为红色
叔叔节点为红色
将“父节点”设为黑色,将“叔叔节点”设为黑色
将“祖父节点”设为红色
如果“祖父节点”为根节点,则将根节点再次变成黑色
叔叔节点为黑色(当前节点是父的右孩子)
叔叔节点为黑色(当前节点是父的左孩子)
将“父节点”设为黑色
将“祖父节点”设为红色
以“祖父节点”为支点进行右旋转
Set 无序、不重复、无索引
不可以存储重复元素
没有索引,不能使用普通for循环遍历
1 2 3 4 5 6 7 8 9 10 11 12 Set<String> set = new TreeSet <>(); set.add("aaa" ); Iterator<String> it = set.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } for (String s : set) { System.out.println(s); }
HashSet:无序、不重复、无索引
LinkedHashSet:有序(存储和取出的元素顺利一致)、不重复、无索引
TreeSet:可排序、不重复、无索引
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
HashSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override public boolean equals (Object o) {}@Override public int hashCode () { return Objects.hash(color, age); }
TreeSet TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public class Student implements Comparable <Student>{ private String name; private int age; public Student (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } @Override public int compareTo (Student o) { int result = this .age - o.age; result = result == 0 ? this .name.compareTo(o.getName()) : result; return result; } } TreeSet<Student> ts = new TreeSet <>(); Student s1 = new Student ("zhangsan" ,28 );Student s2 = new Student ("lisi" ,27 );public class Teacher { private String name; private int age; public Teacher () { } public Teacher (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } } TreeSet<Teacher> teacherSet = new TreeSet <>(new Comparator <Teacher>() { @Override public int compare (Teacher o1, Teacher o2) { int result = o1.getAge() - o2.getAge(); result = result == 0 ? o1.getName().compareTo(o2.getName()) : result; return result; } });
Map
双列集合,一个键对应一个值
键不可以重复,值可以重复
方法名
说明
V put(K key,V value)
添加元素
V remove(Object key)
根据键删除键值对元素
void clear()
移除所有的键值对元素
boolean containsKey(Object key)
判断集合是否包含指定的键
boolean containsValue(Object value)
判断集合是否包含指定的值
boolean isEmpty()
判断集合是否为空
int size()
集合的长度,也就是集合中键值对的个数
获取功能
方法名
说明
V get(Object key)
根据键获取值
Set keySet()
获取所有键的集合
Collection values()
获取所有值的集合
Set<Map.Entry<K,V>> entrySet()
获取所有键值对对象的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Map<String,String> map = new HashMap <String,String>(); map.put("张无忌" , "赵敏1" ); map.put("郭靖" , "黄蓉" ); map.put("杨过" , "小龙女" ); Collection<String> values = map.values(); for (String value : values) { System.out.println(value); } Set<String> keySet = map.keySet(); for (String key : keySet) { String value = map.get(key); System.out.println(key + "," + value); } Set<Map.Entry<String, String>> entrySet = map.entrySet(); for (Map.Entry<String, String> me : entrySet) { String key = me.getKey(); String value = me.getValue(); System.out.println(key + "," + value); } map.forEach((key, value) -> System.out.println(key + "=" + value));
HashMap
HashMap底层是哈希表结构的
依赖hashCode方法和equals方法保证键的唯一
如果键要存储的是自定义对象,需要重写hashCode和equals方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class Student { private String name; private int age; public Student () {} public Student (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public int getAge () { return age; } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Student student = (Student) o; if (age != student.age) return false ; return name != null ? name.equals(student.name) : student.name == null ; } @Override public int hashCode () { int result = name != null ? name.hashCode() : 0 ; result = 31 * result + age; return result; } } HashMap<Student, String> hm = new HashMap <Student, String>(); Student s1 = new Student ("林青霞" , 30 );Set<Student> keySet = hm.keySet(); for (Student key : keySet) { String value = hm.get(key); System.out.println(key.getName() + "," + key.getAge() + "," + value); }
LinkedHashMap 由键决定:有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
TreeMap
TreeMap底层是红黑树结构
依赖自然排序或者比较器排序,对键进行排序
如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Student implements Comparable <Student>{ @Override public int compareTo (Student o) { int result = o.getAge() - this .getAge(); result = result == 0 ? o.getName().compareTo(this .getName()) : result; return result; } } TreeMap<Student,String> tm = new TreeMap <>(); tm.forEach( (Student key, String value)->{ System.out.println(key + "---" + value); } );
可变参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void f (String s, int ... nums) { for (int n : nums) { ... } } f("a" ); f("a" , 1 , 2 , 3 ); f("a" , new int []{1 , 2 });
Collections类
java.utils.Collections 是集合工具类,用来对集合进行操作。
常用方法如下:
public static void shuffle(List<?> list) :打乱集合顺序。
public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> ) :将集合中元素按照指定规则排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class CollectionsDemo { public static void main (String[] args) { ArrayList<Integer> list = new ArrayList <Integer>(); list.add(100 ); list.add(300 ); list.add(200 ); list.add(50 ); Collections.sort(list); System.out.println(list); } } public class Student { private String name; private int age; } public class Demo { public static void main (String[] args) { ArrayList<Student> list = new ArrayList <Student>(); list.add(new Student ("rose" ,18 )); list.add(new Student ("jack" ,16 )); list.add(new Student ("abc" ,20 )); Collections.sort(list, new Comparator <Student>() { @Override public int compare (Student o1, Student o2) { return o1.getAge()-o2.getAge(); } }); for (Student student : list) { System.out.println(student); } } } Student{name='jack' , age=16 } Student{name='rose' , age=18 } Student{name='abc' , age=20 }
不可变集合 是一个长度不可变,内容也无法修改的集合,只能进行查询操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 List<String> list = List.of("张三" , "李四" , "王五" , "赵六" ); Set<String> set = Set.of("张三" , "张三" , "李四" , "王五" , "赵六" ); Map<String, String> map = Map.of("张三" , "南京" , "张三" , "北京" ); HashMap<String, String> hm = new HashMap <>(); hm.put("张三" , "南京" ); hm.put("陈二" , "嘉兴" ); Map<String, String> immutableMap = Map.copyOf(hm);
Stream流
中间方法:一次操作完毕之后,还可以继续进行其他操作
终结方法:一个Stream流只能有一个终结方法,是流水线上的最后一个操作
生成Stream流的方式
Collection体系集合:使用默认方法stream()生成流, default Stream stream()
Map体系集合:把Map转成Set集合,间接的生成流
数组:通过Arrays中的静态方法stream生成流
同种数据类型的多个数据:通过Stream接口的静态方法of(T… values)生成流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 List<String> list = new ArrayList <String>(); Stream<String> listStream = list.stream(); Set<String> set = new HashSet <String>(); Stream<String> setStream = set.stream(); Map<String,Integer> map = new HashMap <String, Integer>(); Stream<String> keyStream = map.keySet().stream(); Stream<Integer> valueStream = map.values().stream(); Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream(); String[] strArray = {"hello" ,"world" ,"java" }; Stream<String> strArrayStream = Arrays.stream(strArray); Stream<String> strArrayStream2 = Stream.of("hello" , "world" , "java" ); Stream<Integer> intStream = Stream.of(10 , 20 , 30 ); int arr1 = {1 , 2 , 3 };String arr2 = {"a" , "b" , "c" }Stream.of(arr1).forEach(s-> System.out.println(s));
中间方法
方法名
说明
Stream filter(Predicate predicate)
用于对流中的数据进行过滤
Stream limit(long maxSize)
返回此流中的元素组成的流,截取前指定参数个数的数据
Stream skip(long n)
跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static Stream concat(Stream a, Stream b)
合并a和b两个流为一个流
Stream distinct()
返回由该流的不同元素(根据 Object.equals(Object) )组成的流
Stream Map(Function<T,R> mapper)
转换流中的数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ArrayList<String> list = new ArrayList <>(); list.add("张三丰" ); list.add("张无忌" ); list.add("王祖贤" ); list.stream().filter(s ->s.startsWith("张" )).forEach(s-> System.out.println(s)); list.stream().limit(3 ).forEach(s-> System.out.println(s)); System.out.println("--------" ); list.stream().skip(3 ).forEach(s-> System.out.println(s)); System.out.println("--------" ); list.stream().skip(2 ).limit(2 ).forEach(s-> System.out.println(s)); Stream<String> s1 = list.stream().limit(4 ); Stream<String> s2 = list.stream().skip(2 ); Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s)); ArrayList<String> strList = new ArrayList <>(); Collections.addAll(strList, "a-1" , "b-2" ); strList.stream().map(s -> Integer.parseInt(s.split("-" )[1 ]));
终结方法
方法名
说明
void forEach(Consumer action)
对此流的每个元素执行操作
long count()
返回此流中的元素数
Object[] toArray()
返回包含此流元素的数组
1 2 3 4 5 6 7 8 9 long count = list.stream().count();list.stream().forEach(s -> System.out.println(s)); Object[] arr1 = list.stream().toArray(); String[] arr2 = list.stream().toArray(value -> new String [value]);
收集方法
方法名
说明
R collect(Collector collector)
把结果收集到集合中
工具类Collectors提供了具体的收集方式
方法名
说明
public static Collector toList()
把元素收集到List集合中
public static Collector toSet()
把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)
把元素收集到Map集合中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 List<Integer> list1 = new ArrayList <>(List.of(1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 10 , 10 , 10 , 10 , 10 )); List<Integer> evenList = list1.stream() .filter(number -> number % 2 == 0 ) .collect(Collectors.toList()); Set<Integer> evenSet = list1.stream() .filter(number -> number % 2 == 0 ) .collect(Collectors.toSet()); List<String> list2 = new ArrayList <>(List.of("zhangsan,23" , "lisi,24" , "wangwu,25" )); Map<String, Integer> ageMap = list2.stream() .filter(s -> Integer.parseInt(s.split("," )[1 ]) >= 24 ) .collect(Collectors.toMap( s -> s.split("," )[0 ], s -> Integer.parseInt(s.split("," )[1 ]) ));
方法引用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 public class FunctionDemo1 { public static void main (String[] args) { Integer[] arr = {3 , 5 , 4 , 1 , 6 , 2 }; Arrays.sort(arr, FunctionDemo1::subtraction); } public static int subtraction (int num1, int num2) { return num2 - num1; } } ArrayList<String> list = new ArrayList <>(); Collections.addAll(list,"1" ,"2" ,"3" ,"4" ,"5" ); list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s)); public class StringOperation { public boolean stringJudge (String s) { return s.startsWith("张" ) && s.length() == 3 ; } } public class FunctionDemo3 { public static void main (String[] args) { ArrayList<String> list = new ArrayList <>(); Collections.addAll(list,"张无忌" ,"周芷若" ,"赵敏" ,"张强" ,"张三丰" ); list.stream().filter(new FunctionDemo3 ()::stringJudge).forEach(s-> System.out.println(s)); list.stream().filter(new FunctionDemo3 ()::stringJudge).forEach(s-> System.out.println(s)); public class StringOperation {...} } } public class Student { private String name; private int age; public Student (String str) { String[] arr = str.split("," ); this .name = arr[0 ]; this .age = Integer.parseInt(arr[1 ]); } } List<Student> newList2 = list.stream().map(Student::new ).collect(Collectors.toList()); list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s)); ArrayList<Integer> numList = new ArrayList <>(); Collections.addAll(numList, 1 , 2 , 3 , 4 , 5 ); Integer[] arr2 = numList.stream().toArray(Integer[]::new );
IO