java基础学习的文章目录
1、泛型
- 从 Java 5 开始,增加了泛型技术
- 什么是泛型?
- 将类型变为参数,提高代码复用率
- 建议的类型参数名称
- T : Type
- E : Element
- K : Key
- N : Number
- V : Value
- S、 U、 V : 2nd, 3rd, 4th types
泛型类型(Generic Type)
- 什么是泛型类型?
- 使用了泛型的类或者接口
- 比如
- java.util.Comparator
- java.util.Comparable
public class Student<T> {
private T score;
public T getScore() {
return score;
}
public void setScore(T score) {
this.score = score;
}
public static void genericSample1() {
// java7以前的写法
// Student<String> stu1 = new Student<String>();
//从java7开始,可以省略右边<>中的类型
Student<String> stu1 = new Student<>();
stu1.setScore("A");
String score1 = stu1.getScore();
System.out.println(score1); //A
Student<Double> stu2 = new Student<Double>();
stu2.setScore(98.5);
Double score2 = stu2.getScore();
System.out.println(score2); //98.5
}
public static void main(String[] args) {
genericSample1();
}
}
多个类型参数
public class Student2<N,S> {
private N no;
private S score;
public Student2(N no, S score) {
super();
this.no = no;
this.score = score;
}
public static void main(String[] args) {
Student2<String, String> stu1 = new Student2<String, String>("E9527", "A++");
Student2<Integer, Double> stu2 = new Student2<Integer, Double>(18, 96.5);
}
}
2、泛型类型的继承【错误】
public class Box<E> {
private E element;
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
public static void main(String[] args) {
Box<String> strBox = new Box<String>();
Box<Integer> intBox = new Box<Integer>();
Box<Object> objBox = new Box<Object>();
strBox = intBox; // error
//如果这个代码能正确的话,请思考下面的代码
objBox = strBox; // error
objBox.setElement(new Object());
// 将Object直接转换为String?
String str = strBox.getElement();
}
}
- 我们知道 Integer继承至Number
- 但是Box 不继承Box
- Box 是继承与Object的
泛型类型的继承【正确】
Iterable<String>
^
|
Collection<String>
^
|
List<String>
^
|
ArrayList<String>
泛型继承的定义:
public interface Collection<E> extends Interable<E>
public interface List<E> extends Collection<E>
public class ArrayList<E> implements List<E>
正确的继承示例:
public static void main(String[] args) {
Iterable<String> it = null;
Collection< String> coll = null;
List<String> li = null;
ArrayList<String> al = null;
it = coll;
coll = li;
li = al;
}
3、原始类型
- 什么是原始类型?
- 没有传递具体的类型给泛型的类型参数
- 当使用了原始类型时,编译器会给出 警告(可以用 @suppressWarnings消除)
- 将非原始类型赋值给原始类型时,编译器没有任何警告和错误
- 将原始类型赋值给非原始类型时,编译器会给出 警告(可以用@suppressWarnings消除)
- Box 是原始类型, Box 是非原始类型
4、集合预览
- java.util 包中有个集合框架(Collections Framework),提供了一大堆常用的数据结构
- ArrayList、 LinkedList、 Queue、 Stack、 HashSet、 HashMap 等
- 数据结构是计算机存储、组织数据的方式
- 线性结构、树形结构、图标结构
- 在实际应用中,根据使用场景来选择最合适的数据结构
-----------------------接口部分----------------------- -----------------------Iterable----------------------- ----------------------collection---------------------- Queue Dequeue List Set Map -----------------------具体的类----------------------- LinkedList ArrayList Stack HashSet HashMap ------------------------抽象类----------------------- AbstractSequentialist Vector AbstractSet AbstractMap -----------------AbstractList--------------- ------------------AbstractCollection---------------------- 思考题:为何 Map 如此独立?跟 Collection、 Iterable 毫无继承关系?
5、ArrayList01_基本使用
数组的局限性
- 数组的局限性
- 无法动态扩容
- 操作元素的过程不够面向对象
- ArrayList 是 Java 中的动态数组
- 一个可以动态扩容的数组
- 封装了各种实用的数组操作
public static void arrayUse() { int[] array = new int[4]; array[0] = 11; array[2] = 22; //输出 [11, 0, 22, 0] System.out.println(Arrays.toString(array)); }ArrayList的常用方法
-
int size()
-
boolean isEmpty()
-
boolean contains(Object o)
-
int indexOf(Object o)
-
int lastIndexOf(Object o)
-
E get(int index)
-
E set(int index, E element)
-
boolean add(E element)
-
boolean add(int index, E element)
-
E remove(int index)
-
boolean remove(Object o)
-
void clear()
-
boolean addAll(Collection<? extends E> c)
-
boolean addAll(int index, Collection<? extends E> c)
-
boolean removeAll(collection<?> c)
-
boolean retainAll(collection<?> c)
-
void forEach(Consumer<? supper E> action)
-
void sort(Comparator<? supper E> c)
-
Object[] toArray()
-
<T> T[] toArray(T[] a)
-
void trimToSize()
-
void ensureCapacity(int minCapacity)
ArrayList基本使用
@SuppressWarnings("unchecked") public static void arrayListUse() { @SuppressWarnings("rawtypes") ArrayList list = new ArrayList(); list.add(11); list.add(false); list.add(null); list.add(3.14); list.add(0, "Jack"); list.add("8"); System.out.println(list.indexOf(11));//3 System.out.println(list.size());//6 System.out.println(list);//[Jack, 11, false, null, 3.14, 8] }retainAll使用示例
public static void listRetain() { List<Integer> list1 = new ArrayList<Integer>(); list1.add(11); list1.add(22); list1.add(33); list1.add(44); List<Integer> list2 = new ArrayList<Integer>(); list2.add(22); list2.add(44); //从list1中删除list2中元素以外的所有元素 list1.retainAll(list2); //[22, 44] System.out.println(list1); }6、ArrayList02_toArray
public static void toArray() { List<Integer> list1 = new ArrayList<Integer>(); list1.add(11); list1.add(22); list1.add(33); Object[] array1 = list1.toArray(); System.out.println(array1);//[Ljava.lang.Object;@15db9742 Integer[] array2 = list1.toArray(new Integer[0]); System.out.println(array2);//[Ljava.lang.Integer;@6d06d69c System.out.println(Arrays.deepToString(array2));//[11, 22, 33] }7、ArrayList03_遍历
public static void enumList() { List<Integer> list = new ArrayList<Integer>(); list.add(11); list.add(22); list.add(33); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } Iterator<Integer> it = list.iterator(); while(it.hasNext()) { System.out.println(it.next()); } for (Integer integer : list) { System.out.println(integer); } list.forEach((obj)->{ System.out.println(obj); }); }for-each格式
for(元素类型 变量名: 数组\Iterable) { }- 实现了 Iterable 接口的对象,都可以使用 for-each 格式遍历元素
- 比如 List、 Set 等
- Iterable 在使用 foreach 格式遍历元素时,本质是使用了 Iterator 对象
8、Iterable_Iterator
public class ClassRoom implements Iterable<String>{ private String[] students; public ClassRoom(String... students) { super(); this.students = students; } @Override public Iterator<String> iterator() { return new ClassRoomIterator(); } private class ClassRoomIterator implements Iterator<String> { private int index; @Override public boolean hasNext() { return index < students.length; } @Override public String next() { return students[index++]; } } public static void main(String[] args) { ClassRoom room = new ClassRoom("jack", "Rose"); for (String string : room) { System.out.println(string); } } }9、ArrayList04_扩容原理
- ArrayList 的最小容量是 10
- 每次扩容时,新容量是旧容量的 1.5 倍
ArrayList的内存结构
size elementData10、遍历的注意点01
- 需求:通过遍历的方式,挨个删除所有的元素
错误删除示例1:
public static void errorRemove() { List<Integer> list = new ArrayList<Integer>() ; list.add(11); list.add(22); list.add(33); list.add(44); list.add(55); //java.lang.IndexOutOfBoundsException int size = list.size(); for (int i = 0; i < size; i++) { list.remove(i); } }错误删除示例2:
// 没有删除完全 for (int i = 0; i < list.size(); i++) { list.remove(i); } System.out.println(list);//[22, 44]错误删除示例3:
// java.util.ConcurrentModificationException for (Integer integer : list) { list.remove(integer); }错误删除示例4:
// java.util.ConcurrentModificationException list.forEach((e)->{ list.remove(e); });- 如果希望在遍历元素的同时删除元素
- 请使用 Iterator 进行遍历
- 然后使用 Iterator 的 remove 方法删除元素
正确的示例:
Iterator<Integer> it = list.iterator(); while (it.hasNext()) { it.next(); it.remove(); } System.out.println(list); //[]- 使用迭代器、 forEach 遍历集合元素时,若使用了集合自带的方法修改集合的长度(比如 add、 remove 等方法)
- 那么会抛出 java.util.ConcurrentModificationException 异常
- modCount++;
11、遍历的注意点02
- 遍历前 备份 modCount
- 遍历的时候发现modCount改变,证明遍历的时候操作了数组
12、ListIterator
- ListIterator 继承自 Iterator,在 Iterator 的基础上增加了一些功能
- boolean hasNext();
- E next();
- boolean hasPrevious();
- E previsous();
- int nextIndex();
- int previousIndex();
- void remove();
- void set(E e);
- void add(E e);
ListIterator使用
public static void listsEterator() { List<Integer> list = new ArrayList<Integer>() ; list.add(11); list.add(22); list.add(33); list.add(44); list.add(55); ListIterator<Integer> it = list.listIterator(); while (it.hasNext()) { System.out.println(it.next()); } System.out.println("--------"); while (it.hasPrevious()) { System.out.println(it.previous()); } }ListIterator使用示例
public static void listIteratorSample() { List<Integer> list = new ArrayList<Integer>() ; list.add(11); list.add(22); list.add(33); ListIterator<Integer> it = list.listIterator(); while (it.hasNext()) { it.set(it.next() + 55); } System.out.println(list); }ListIterator使用
public static void listIteratorSample2() { List<Integer> list = new ArrayList<Integer>() ; list.add(11); list.add(22); list.add(33); ListIterator<Integer> it = list.listIterator(); while (it.hasNext()) { it.add(77); it.next(); it.add(77); } System.out.println(list);//[77, 11, 77, 77, 22, 77, 77, 33, 77] }13、ArrayList05_容量相关方法
- void trimToSize(void)
- void ensureCapacity(int)
14、泛型方法01
- 什么是泛型方法?
- 使用了泛型的方法(实例方法、静态方法、构造方法),比如 Arrays.sort(T[], Comparator<T>)
public static void genericMethod() { Student2<String, String> s1 = new Student2<String, String>("01", "A"); set(s1, "02", "A+"); Student2<Integer, Double> s2 = new Student2<Integer, Double>(3, 99.9); set(s2, 4, 99.0); //完整写法 Student2.<Integer, Double>set(s2, 5, 90.1); System.out.println(s2); } static <T1, T2> void set(Student2<T1, T2> stu, T1 no, T2 score) { stu.setNo(no); stu.setScore(score); }15、泛型方法02
泛型方法使用示例
public static void main(String[] args) { List<Box<Integer>> boxes = new ArrayList<Box<Integer>>(); addBox(11, boxes); addBox(22, boxes); addBox(33, boxes); } public static <T> void addBox(T element, List<Box<T>> boxs) { Box<T> box = new Box<T>(element); boxs.add(box); }返回值进行类型推断
public static void main(String[] args) { /* public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; } 说明通过返回类型也能进行类型推断*/ List<String> list1 = Collections.emptyList(); List<Integer> list2 = Collections.emptyList(); }泛型方法-构造方法
public class Persion<T> { private T age; public <E> Persion(E name, T age) { } } Persion<Integer> persion = new Persion<>("Jack", 20); Persion<String> persion = new Persion<>("Jack", "80后");public class Box<E> { private E element; // 说明泛型类型E 只能用在实例方法上,和实例挂钩 public static void test(E element) { // error: Cannot make a static reference to the non-static type E } }16、限制类型参数01
- 可以通过 extends 对类型参数增加一些限制条件,比如
- extends 后面可以跟上类名、接口名,代表 T 必须是 A 类型,或者继承、实现 A
- 可以同时添加多个限制,比如 <T extends A & B & C>,代表 T 必须同时满足 A、 B、 C
17、限制类型参数02
限制类型的示例:
public class Persion implements Comparable<Persion>{ private int age; public Persion(int age) { super(); this.age = age; } @Override public int compareTo(Persion o) { if (o == null) { return 1; } return age - o.age; } @Override public String toString() { return "Persion [age=" + age + "]"; } } public class Sort { public static void main(String[] args) { Double[] ds = {5.6, 3.4, 8.8, 4.6}; System.out.println(getMax(ds)); //8.8 Integer[] is = {4,19, 3, 28, 56}; //56 System.out.println(getMax(is)); Persion[] persions = { new Persion(11), new Persion(88), new Persion(55) }; System.out.println(getMax(persions)); //Persion [age=88] } public static <T extends Comparable<T>> T getMax (T[] arrary) { if (arrary == null || arrary.length == 0) { return null; } T max = arrary[0]; for (int i = 1; i < arrary.length; i++) { if (arrary[i] == null) { continue; } if (arrary[i].compareTo(max) > 0) { max = arrary[i]; } } return max; } }18、排序01
sort示例1:
public static void sort1() { Persion[] persions = { new Persion(11), new Persion(88), new Persion(55) }; Arrays.sort(persions); //[Persion [age=11], Persion [age=55], Persion [age=88]] System.out.println(Arrays.deepToString(persions)); }从大到小的排列方式
public static void sort1() { Persion[] persions = { new Persion(11), new Persion(88), new Persion(55) }; //从大到小排列 Arrays.sort(persions, new Comparator<Persion>() { @Override public int compare(Persion o1, Persion o2) { return o2.getAge() - o1.getAge(); } }); //[Persion [age=88], Persion [age=55], Persion [age=11]] System.out.println(Arrays.deepToString(persions)); }Comparator 可以提供多种比较方式。
- 如果数组元素本身具备可比较性(实现了java.lang.Comparable接口)
- 可以直接使用Arrays.sort方法进行排序
- java.util.Comparator的存在意义?
- 可以在不修改类源代码的前提下,修改默认的比较方式(比如官方类,第三方类)
- 可以让一个类提供多种比较方式
19、排序02
排序示例:
public class ComparableStudent<T extends Comparable<T>> implements Comparable<ComparableStudent<T>>{ private T score; public ComparableStudent(T score) { super(); this.score = score; } @Override public int compareTo(ComparableStudent<T> o) { if (null == o) return 1 ; if (score != null) return score.compareTo(o.score); return o.score == null ? 0 : -1; } @Override public String toString() { return "ComparableStudent [score=" + score + "]"; } public static void main(String[] args) { ComparableStudent[] students = { new ComparableStudent(11), new ComparableStudent(88), new ComparableStudent(55) }; //从大到小排列 Arrays.sort(students); //[ComparableStudent [score=11], ComparableStudent [score=55], ComparableStudent [score=88]] System.out.println(Arrays.toString(students)); } }20、通配符01
- 在泛型中,问号(?)被称为是通配符
- 通常用作变量类型、返回值类型的类型参数
- 不能用作泛型方法调用、泛型类型实例化、泛型类型定义的类型参数
通配符-上界
- 可以通过 extends 设置类型参数的上界
public class WildCards { public static void main(String[] args) { Box<Integer> b1 = null; Box<Number> b2 = null; Box<? extends Number> b3 = null; Box<? extends Integer> b4 = null; //模糊的写法,可以赋值 b4 = b1; //ok b4 = b2; //error } }public static void main(String[] args) { List<Integer> is = Arrays.asList(1,2,3); System.out.println(sum(is)); //6.0 List<Double> ds = Arrays.asList(1.0,2.0,3.0); System.out.println(sum(ds)); //6.0 } static double sum(List<? extends Number> list) { double s = 0.0; for (Number n: list) { s+= n.doubleValue(); } return s; }通配符下界
- 可以通过 super 设置类型参数的下界
- 所谓下界,必须大于等于他
- ? super Integer 理解为类型super(超过)Integer
void testLower(Box<? super Integer> box) {} Box<Integer> p1 = null; Box<Number> p2 = null; Box<? super Integer> p3 = null; Box<? super Number> p4 = null; testLower(p1); testLower(p2); testLower(p3); testLower(p4);下界示例代码:
public static void main(String[] args) { List<Integer> is = new ArrayList<Integer>(); addNumbers(is); System.out.println(is); //[0, 1, 2, 3, 4] List<Number> ns = new ArrayList<Number>(); addNumbers(ns); System.out.println(ns);//[0, 1, 2, 3, 4] } static void addNumbers(List<? super Integer> list) { for (int i = 0; i < 5; i++) { list.add(i); } }通配符-无限制
什么都能传进去的示例:
public static void main(String[] args) { Box<Integer> p1 = null; Box<String> p2 = null; Box<Object> p3 = null; Box<? extends Number> p4 = null; Box<? super String> p5 = null; Box<?> p6 = null; test3(p1); test3(p2); test3(p3); test3(p4); test3(p5); test3(p6); } static void test3(Box<?> box) {}无限制通配符示例代码:
public static void main(String[] args) { List<Integer> is = Arrays.asList(1,2, 3); printList(is);//1 2 3 List<Double> ds = Arrays.asList(1.2, 2.3, 3.5); printList(ds);1.2 2.3 3.5 } static void printList(List<?> list) { for (Object object : list) { System.out.print(object + " "); } System.out.println(); }21、通配符02
通配符的继承
Box<?> ^ ^ | | Box<? extends Number> Box<? super Integer> ^ ^ | | Box<? extends Integer> Box<? super Number> ^ ^ | | Box<Integer> Box<Number> 核心思路; 包含的范围大的是父类22、泛型的使用限制
- 编译器在解析 List.set(int index, E element) 时,无法确定 E 的真实类型,所以报错
static void foo(List<?> list) { Object obj = list.get(0); //错误的原因:编译器在编译的时候需要确定类型,这里没有确定 // 假设传递的是Integer,这里这是的Object就会报错 list.set(0, obj); //error list.set(0, list.get(0)); // error }如果想编译过,用泛型方法,饶个弯:
static <T> void foo1(List<T> list) { T obj = list.get(0); //错误的原因:编译器在编译的时候需要确定类型,这里没有确定 // 假设传递的是Integer,这里这是的Object就会报错 list.set(0, obj); //error list.set(0, list.get(0)); // error }- 基本类型不能作为类型参数
Map<int, char> map1 = new HashMap<>(); //error Map<Integer, Character> map2 = new HashMap<>(); //ok- 不能创建类型参数的示例
public class Box<E> { public void add(Class<E> class) throws Exception { E e1 = new E(); // error E e2 = class.newInstance(); // ok } }- 不能用类型参数定义静态变量
public class Box<E> { private class E value; // error } Box<Integer> box1 = new Box<>(); Box<String> box2 = new Box<>(); // 请问静态变量value是什么类型?答:没法确定- 泛型类型的类型参数不能用在静态方法上
public class Box<E> { public static void show(E value) {} // error }- 类型参数不能跟 instanceof 一起使用
ArraryList<Integer> list = new ArraryList<>(); if(list instanceof ArraryList<Integer>) { // error }- 不能创建带有类型参数的数组
Box<Integer>[] boxes1 = new Box<Integer>[];// error Box<Integer>[] boxes2 = new Box[4]; //or- 下面的方法不属于重载
// error void test(Box<Integer> box) { } void test(Box<String> box) { }void test(Box<? extends Number> box) { } void test(Box<String> box) { }- 不能定义泛型的异常类
// error public class MyException<T> extends Exception { }- catch 的异常类型不能用类型参数
public static <T extend Exception> void test(Box<T> box) { try{ } catch(T e) { } }- 下面的代码是正确的
class Parser<T extends Exception> { //ok public void parse(File file) throws T { } }23、函数式接口01_Supplier
- java.util.function 包中提供了很多常用的函数式接口
- Supplier(美 [səˈplaɪər])
- Consumer(美 [kənˈsuːmər])
- Predicate(美 [ˈpredɪkeɪt])
- Function(美 [ˈfʌŋkʃn])
- ......
Supplier
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }- 有时使用 Supplier 传参,可以避免代码的浪费执行(有必要的时候再执行)
public static void main(String[] args) { String s1 = "A"; String s2 = "B"; String s3 = "C"; getFirstNotEmptyString(s1, new Supplier<String>() { @Override public String get() { //这种情况就没有打印输出日志 System.out.println("调用了supplier"); return s1 + s2 + s3; } }); } static String getFirstNotEmptyString(String s1, Supplier<String> s2) { if (s1 != null && s1.length() != 0) { return s1; } if (s2 == null) { return null; } String str = s2.get(); return (str != null && str.length() > 0) ? str : null; } 类似于|| 的短路功能24、函数式接口02_Consumer
定义:
@FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }使用示例:
public static void main(String[] args) { int[] nums = {11,2,33,44}; forEach(nums, (n) -> { String result = ((n & 1) == 0) ? "偶数" : "奇数"; System.out.println(n + "是" + result); }); } static void forEach(int[] nums, Consumer<Integer> consumer ) { if (nums == null || consumer == null) { return; } for (int i : nums) { consumer.accept(i); } } 回调就是将参数传出去andThen 使用示例:
public static void main(String[] args) { int[] nums = {11,2,33,44}; forEach(nums, (n) -> { String result = ((n & 1) == 0) ? "偶数" : "奇数"; System.out.println(n + "是" + result); },(n) -> { String result = ((n %3 ) == 0) ? "能" : "不能"; System.out.println(n + result + "能被3整除"); }); } static void forEach(int[] nums, Consumer<Integer> consumer , Consumer<Integer> consumer2) { if (nums == null || consumer == null) { return; } for (int i : nums) { consumer.andThen(consumer2).accept(i); } }输出:
11是奇数 11不能能被3整除 2是偶数 2不能能被3整除 33是奇数 33能能被3整除 44是偶数 44不能能被3整除25、函数式接口03_Predicate
定义:
public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate<T> negate() { return (t) -> !test(t); } /** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param <T> the type of arguments to the predicate * @param targetRef the object reference with which to compare for equality, * which may be {@code null} * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }使用示例:
public static void main(String[] args) { int[] nums = {11,22,33,44}; String result = join(nums, (n)->{ if ((n&1) == 0) { return true; } else { return false; } }); System.out.println(result); //22_44 } static String join(int[] nums, Predicate<Integer> p) { if (nums == null || p == null) { return null; } StringBuilder sb = new StringBuilder(); for (int i : nums) { if (p.test(i)) { sb.append(i).append("_"); }; } sb.deleteCharAt(sb.length()-1); return sb.toString(); } 删选元素,符合规则的拼接到一起26、函数式接口04_Function
定义:
/** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * Returns a function that always returns its input argument. * * @param <T> the type of the input and output objects to the function * @return a function that always returns its input argument */ static <T> Function<T, T> identity() { return t -> t; } }使用示例:
public static void main(String[] args) { String[] strs = {"12", "400", "12"}; int result = sum2(strs, (str)-> { return Integer.valueOf(str); }); System.err.println(result); //424 } static int sum2(String[] strs, Function<String, Integer> f) { if (strs == null || f == null) { return 0; } int result = 0; for(String str: strs) { result += f.apply(str); } return result; }27、LinkedList
- LinkedList 是一个双向链表
- 实现了 List 接口
- API 跟 ArrayList 类似
28、Linked_ArrayList对比
- ArrayList :开辟、销毁内存空间的次数相对较少,但可能造成内存空间浪费(可以通过缩容解决)
- LinkedList :开辟、销毁内存空间的次数相对较多,但不会造成内存空间的浪费
- 如果频繁在尾部进行添加、 删除操作, ArrayList、 LinkedList 均可选择
- 如果频繁在头部进行添加、 删除操作,建议选择使用 LinkedList
- 如果有频繁的(在任意位置) 添加、 删除操作,建议选择使用 LinkedList
- 如果有频繁的查询操作(随机访问操作),建议选择使用 ArrayList
29、Stack_Queue
- Stack,译为“栈”,只能在一端进行操作
- 往栈中添加元素的操作,一般叫做 push, 入栈
- 从栈中移除元素的操作,一般叫做 pop,出栈(只能移除栈顶元素,也叫做:弹出栈顶元素)
- 后进先出的原则, Last In First Out, LIFO
- 注意:这里说的“栈”与内存中的“栈空间”是两个不同的概念
Stack 常用方法
E push(E item) E pop() E peek() int size() boolean empty() int search(Object o)Queue
- Queue,译为“队列” ,只能在头尾两端进行操作
- 队尾(rear):只能从队尾添加元素,一般叫做 入队
- 队头(front):只能从队头移除元素,一般叫做 出队
- 先进先出的原则, First In First Out, FIFO
boolean add(E e) //入队 boolean offer(E e) // 入队 E remove(); //出队 E poll() //出队 E element() //返回队头 boolean isEmpty(); int size();30、HashSet_TreeSet
- LinkedHashSet 在 HashSet 的基础上,记录了元素的添加顺序
- TreeSet 要求元素必须具备可比较性,默认按照从小到大的顺序遍历元素
31、HashMap_TreeMap
-
HashMap 存储的是键值对(key-value), Map 译为“映射”,有些编程语言中叫做“字典”
-
LinkedHashMap 在 HashMap 的基础上,记录了元素的添加顺序
-
TreeMap 要求 key 必须具备可比较性,默认按照从小到大的顺序遍历 key
-
List 的特点
- 可以存储重复的元素
- 可以通过索引访问元素
-
Set 的特点
- 不可以存储重复的元素
- 不可以通过索引访问元素
-
Map 的特点
- 不可以存储重复的 key,可以存储重复的 value
- 不可以通过索引访问 key-value
-
Set 的底层是基于 Map 实现的
- HashSet 底层用了 HashMap
- LinkedHashSet 底层用了 LinkedHashMap
- TreeSet 底层用了TreeMap
32、Collections
- java.util.Collections 是一个常用的集合工具类,提供了很多实用的静态方法
- java.util 包中有个集合框架(Collections Framework),提供了一大堆常用的数据结构