一宝惰、方法引用與構造函數(shù)引用
- 說明:方法引用是?種更簡潔易懂的lambda表達式钟些,操作符是雙冒號::,用來直接訪問類或者實例已經存在的方法或構造方法
- 通過方法引用,可以將方法的引?賦值給?個變量
- 語法:左邊是容器(可以是類名鳖敷,實例名),中間是" :: "程拭,右邊是相應的方法名
- 靜態(tài)方法定踱,則是ClassName::methodName。如 Object ::equals
- 實例方法恃鞋,則是Instance::methodName
- 構造函數(shù)崖媚,則是 類名::new;
- 單個參數(shù)
Function<入?yún)?, 返回類型> func = 方法引用
應用 func.apply(入?yún)?; - 兩個參數(shù)
BiFunction<入?yún)?,入?yún)?, 返回類型> func = 方法引用
應用 func.apply(入?yún)?,入?yún)?);
class User {
private String username;
private Integer age;
public User() {}
public User(String username) {
this.username = username;
}
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
}
public class Test{
public static void main(String[] args) {
// 使用雙冒號::來構造靜態(tài)函數(shù)引用
Function<String, Integer> fun = Integer::parseInt;
Integer value = fun.apply("1024");
System.out.println(value);
// 使用雙冒號::來構造非靜態(tài)函數(shù)引用
String content = "測試使用";
Function<Integer, String> func = content::substring;
String result = func.apply(1);
System.out.println(result);
// 構造函數(shù)引用,多個參數(shù)
BiFunction<String, Integer, User> biFunction = User::new;
User user1 = biFunction.apply("Test", 28);
System.out.println(user1.toString());
//構造函數(shù)引用山宾,單個參數(shù)
Function<String, User> function = User::new;
User user2 = function.apply("Test");
System.out.println(user2.toString());
// 函數(shù)引用也是一種函數(shù)式接用至扰,可以將函數(shù)引用作為方法的參數(shù)
sayHello(String::toUpperCase, "Test");
}
/**
*
* @param func 函數(shù)引用
* @param param 對應的參數(shù)
*/
private static void sayHello(Function<String, String> func, Stringparam) {
String result = func.apply(param);
System.out.println(result);
}
}
二鳍徽、JDK8之流Stream
- Stream 中文稱為 “流”资锰,通過將集合轉換為這么?種叫做 “流”的元素隊列,通過聲明性方式阶祭,能夠對集合中的每個元素進行?系列并行或串行的流水線操作绷杜。
-
元素是特定類型的對象,所以元素集合看作?種流濒募, 流在管道中傳輸鞭盟, 且可以在管道的節(jié)點上進行處理, ?如 排序瑰剃,聚合齿诉,過濾等操作。
image.png - 操作詳情
- 數(shù)據(jù)元素便是原始集合晌姚,如List粤剧、Set、Map等
- 生成流挥唠,可以是串行流stream() 或者并行流 parallelStream()
- 中間操作抵恋,可以是 排序,聚合宝磨,過濾弧关,轉換等
- 終端操作,很多流操作本身就會返回?個流唤锉,所以多個操作可以直接連接起來世囊,最后統(tǒng)?進行收集
List<String> list = Arrays.asList("aaaa","bbbb","cccc","dddd","eeee);
List<String> resultList = list.stream().map(obj->"遍歷:"+obj).collect(Collectors.toList());
System.out.println(resultList);
三、JDK8之流操作map和filter函數(shù)
- map函數(shù)
- 將流中的每?個元素 T 映射為 R(類似類型轉換)
- 類似遍歷集合窿祥,對集合的每個對象做處理
- 場景:轉換對象株憾,如javaweb開發(fā)中集合里面的DO對象轉換為DTO對象
List<String> list = Arrays.asList("aaaa","bbbb","cccc","dddd","eeee);
List<String> resultList = list.stream().map(obj->"遍歷:"+obj).collect(Collectors.toList());
System.out.println(resultList);
@Data
class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name= name;
this.age = age;
}
}
@Data
class UserDTO {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name= name;
this.age = age;
}
}
public class Test{
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("peter",11),new User("jack",12),new User("tom",10),new User("marry",14));
List<UserDTO> userDTOList = list.stream().map(obj->{
UserDTO userDTO = new UserDTO(obj.getName(),obj.getAage());
return userDTO;
}).collect(Collectors.toList());
System.out.println(userDTOList);
}
}
- filter函數(shù)
- 用于通過設置的條件過濾出元素
- 場景:主要用于篩選過濾出符合條件的元素
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
List<String> resultList = list.stream().filter(obj -> obj.length() >5).collect(Collectors.toList());
System.out.println(resultList);
四、JDK8之流操作limit和sorted函數(shù)
- limit函數(shù)
- 截斷流使其最多只包含指定數(shù)量的元素
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
//limit截取
List<String> resultList=list.stream().sorted(Comparator.comparing(String::length).reversed()).limit(3).collect(Collectors.toList());
System.out.println(resultList);
- sorted函數(shù)
- sorted() 對流進?自然排序, 其中的元素必須實現(xiàn)Comparable 接口
- sorted(Comparator<? super T> comparator) 用來自定義升降序
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
List<String> resultList1 = list.stream().sorted().collect(Collectors.toList());
List<String> resultList2 = list.stream().sorted(Comparator.comparing(obj -> obj.length())).collect(Collectors.toList());
List<String> resultList3 = list.stream().sorted(Comparator.comparing(obj ->obj.length(),Comparator.reverseOrder())).collect(Collectors.toList());
List<String> resultList4 = list.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
五壁肋、JDK8之流操作allMatch和anyMatch函數(shù)
- allMatch函數(shù)
- 檢查是否匹配所有元素号胚,只有全部符合才返回true
List<String> list = Arrays.asList("springboot", "springcloud", "redis","git", "netty", "java", "html", "docker");
boolean flag = list.stream().allMatch(obj->obj.length()>1);
System.out.println(flag);
- anyMatch函數(shù)
- 檢查是否?少匹配?個元素
List<String> list = Arrays.asList("springboot", "springcloud", "redis","git", "netty", "java", "html", "docker");
boolean flag = list.stream().anyMatch(obj->obj.length()>18);
System.out.println(flag)
六籽慢、JDK8之流操作max和min函數(shù)
- max和min函數(shù)
- 最大值和最小值
@Data
class Student {
private int age;
public Student(int age) {
this.age = age;
}
}
public class Test{
public static void main(String[] args) {
List<Student> list = Arrays.asList(new Student(32),newStudent(33),new Student(21),new Student(29),new Student(18));
//最大值
Optional<Student> optional = list.stream().max((s1, s2)->Integer.compare(s1.getAge(),s2.getAge()));
//最小值
Optional<Student> optional = list.stream().min((s1, s2)->Integer.compare(s1.getAge(),s2.getAge()));
System.out.println(optional.get().getAge());
}
}
七、JDK8之并行流parallelStream
- 為什么會有這個并行流
- 集合做重復的操作猫胁,如果使?串行執(zhí)行會相當耗時箱亿,因此?般會采用多線程來加快, Java8的paralleStream用fork/join框架提供了并發(fā)執(zhí)行能力弃秆。
- 底層原理
(1) 線程池(ForkJoinPool)維護?個線程隊列
(2) 可以分割任務届惋,將父任務拆分成子任務,完全貼合分治思想
//順序輸出
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.stream().forEach(System.out::println);
//并?亂序輸出
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(System.out::println);
- paralleStream并行是否?定比Stream串行快菠赚?
- 錯誤脑豹,數(shù)據(jù)量少的情況,可能串行更快衡查,F(xiàn)orkJoin會耗性能
- 多數(shù)情況下并行比串行快瘩欺,是否可以都用并行
(1) 不行,部分情況會有線程安全問題拌牲,parallelStream里?使用的外部變量俱饿,比如集合?
定要使用線程安全集合,不然就會引發(fā)多線程安全問題塌忽。
for(int i=0;i<10;i++) {
//List list = new ArrayList();
List list = new CopyOnWriteArrayList();
IntStream.range(0, 100).parallel().forEach(list::add);
System.out.println(list.size());
}
image.png
image.png
八拍埠、JDK8之reduce操作
-
什么是reduce操作
- 聚合操作,中文意思是 “減少”
- 根據(jù)?定的規(guī)則將Stream中的元素進行計算后返回?個唯?的值
常用方法一
Optional<T> reduce(BinaryOperator<T> accumulator);
//accumulator 計算的累加器
//例子: 第?個元素相加和第?個元素相加土居,結果再和第三個元素相加枣购,直到全部相加完成
int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1+ item2).get();
//不?lambda的寫法
int result = Stream.of(1,2,3,4,5).reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer item1, Integer item2) {
return item1 + item2;
}
}).get();
- 常用方法二
T reduce(T identity, BinaryOperator<T> accumulator);
//identity ?戶提供?個循環(huán)計算的初始值
//accumulator 計算的累加器
//例子: 100作為初始值,然后和第?個元素相加擦耀,結果在和第?個元素相加棉圈,直到全部相加完成
int value = Stream.of(1, 2, 3, 4,5).reduce(100, (sum, item) -> sum + item);
- 例子應用
int value = Stream.of(1645, 234345, 32,44434,564534,435,34343542,212).reduce( (item1, item2) -> item1 > item2 ? item1 : item2 ).get();
System.out.println(value);
九、JDK8之集合的foreach
- 集合遍歷的方式
- for循環(huán)
- 迭代器 Iterator
- 注意點
- 不能修改包含外部的變量的值
- 不能用break或者return或者continue等關鍵詞結束或者跳過循環(huán)
- Jdk8里面的新增接口
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
- 使用案例
List<Student> results = Arrays.asList("aaaa","bbbb","ccccc","ddddd","eeeee");
results.forEach(obj->{System.out.println(obj.toString());});
十埂奈、JDK8之collector收集器
- collect()方法的作用
- ?個終端操作, 用于對流中的數(shù)據(jù)進行歸集操作迄损,collect方法接受的參數(shù)是?個Collector
- 有兩個重載方法,在Stream接口??
//重載?法?
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R>combiner);
//重載?法?
<R, A> R collect(Collector<? super T, A, R> collector);
- Collector的作用
- 就是收集器账磺,也是?個接口, 它的工具類Collectors提供了很多工廠方法
- Collectors 的作用
- 工具類芹敌,提供了很多常見的收集器實現(xiàn)
(1)Collectors.toList()
- 工具類芹敌,提供了很多常見的收集器實現(xiàn)
//ArrayList::new,創(chuàng)建?個ArrayList作為累加器
// List::add垮抗,對流中元素的操作就是直接添加到累加器中reduce操作, 對?任務歸集結果addAll氏捞,后?個子任務的結果直接全部添加到前?個子任務結果中
// CH_ID 是?個unmodifiableSet集合
public static <T> Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,(left, right) -> {left.addAll(right); return left; }, CH_ID);
}
- Collectors.toMap()
- Collectors.toSet()
- Collectors.toCollection() :??定義的實現(xiàn)Collection的數(shù)據(jù)結構收集
Collectors.toCollection(LinkedList::new)
Collectors.toCollection(CopyOnWriteArrayList::new)
Collectors.toCollection(TreeSet::new)
十一、JDK8之joining函數(shù)
- 拼接函數(shù) Collectors.joining
//3種重載?法
Collectors.joining()
Collectors.joining("param")
Collectors.joining("param1", "param2", "param3")
- 其中?個的實現(xiàn)
public static Collector<CharSequence, ?, String> joining() {
return new CollectorImpl<CharSequence, StringBuilder, String>(
StringBuilder::new, StringBuilder::append,(r1, r2) -> { r1.append(r2); return r1; },StringBuilder::toString, CH_NOID);
}
- 該方法可以將Stream得到?個字符串冒版, joining函數(shù)接受三個參數(shù)液茎,分別表示 元素之間的連接符、前綴和后綴。
String result = Stream.of("springboot", "mysql", "html5","css3").collect(Collectors.joining(",", "[", "]"));
十二捆等、JDK8之收集器 partitioningBy分組
- Collectors.partitioningBy 分組滞造,key是boolean類型
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? superT> predicate) {
return partitioningBy(predicate, toList());
}
- 例子: 根據(jù)list里面進行分組,字符串長度大于4的為?組栋烤,其他為另外?組
List<String> list = Arrays.asList("java", "springboot","HTML5","nodejs","CSS3");
Map<Boolean, List<String>> result = list.stream().collect(partitioningBy(obj -> obj.length() > 4));
十三谒养、JDK8之收集器 group by分組
- 分組 Collectors.groupingBy()
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<?super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
- 例子:根據(jù)學生所在的省份,進行分組
@Data
class Student {
private String province;
private int age;
public Student(String province, int age) {
this.age = age;
this.province = province;
}
}
public class Test{
public static void main(String[] args) {
List<Student> students = Arrays.asList(new Student("廣東", 23), newStudent("廣東", 24), new Student("廣東", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
Map<String, List<Student>> listMap = students.stream().collect(Collectors.groupingBy(obj -> obj.getProvince()));
listMap.forEach((key, value) -> {
value.forEach(obj -> {
System.out.println(obj.getAge());
});
});
}
}
十四明郭、JDK8之summarizing集合統(tǒng)計
- summarizing 統(tǒng)計相關, 下面是summarizingInt的源碼
- 作用:可以?個方法把統(tǒng)計相關的基本上都完成
- 分類
- summarizingInt
- summarizingLong
- summarizingDouble
public static <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(IntSummaryStatistics::new,(r, t) -> r.accept(mapper.applyAsInt(t)),(l, r) -> { l.combine(r); return l; }, CH_ID);
}
- 例子:統(tǒng)計學生的各個年齡信息
@Data
class Student {
private String province;
private int age;
public Student(String province, int age) {
this.age = age;
this.province = province;
}
}
public class Test{
public static void main(String[] args) {
List<Student> students = Arrays.asList(new Student("廣東", 23), newStudent("廣東", 24), new Student("廣東", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
IntSummaryStatistics summaryStatistics = students.stream().collect(Collectors.summarizingInt(Student::getAge));
System.out.println("平均值:" + summaryStatistics.getAverage());
System.out.println("人數(shù):" + summaryStatistics.getCount());
System.out.println("最大值:" + summaryStatistics.getMax());
System.out.println("最小值:" + summaryStatistics.getMin());
System.out.println("總和:" + summaryStatistics.getSum());
}
}
十五买窟、 JDK8 新的內存空間和異常處理
- JVM 種類有很多,比如 Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM薯定,我們講的是Hotspot才有始绍,JRockit以及J9是沒有這個區(qū)域。
- JVM內存知識 在JDK8之前的HotSpot JVM话侄,有個區(qū)域叫做“永久代(permanent generation)亏推, 通過在命令行設置參數(shù)-XX:MaxPermSize來設定永久代最大可分配的內存空間,如果JDK8??設置了PermSize 和MaxPermSize 會被忽略并給出警告满葛。
- 作用:該塊內存主要是被JVM?來存放 class 和 mate 信息的径簿,當 class 被加載 loader 的時候就會被存儲到該內存區(qū)中,如方法的編譯信息及字節(jié)碼嘀韧、常量池和符號解析、類的層級信息缠捌,字段锄贷,名字等。
- 這個異常應該熟悉 java.lang.OutOfMemoryError: PermGen space曼月,原因是: 永久代空間不夠谊却,類太多導致
- jdk8的修改 JDK8 HotSpot JVM 使用本地內存來存儲類元數(shù)據(jù)信息,叫做 元空間(Metaspace)哑芹,在默認情況下Metaspace的大小只與本地內存大小有關炎辨。
- 常用的兩個參數(shù) -XX:MetaspaceSize=N 指Metaspace擴容時觸發(fā)FullGC的初始化閾值-XX:MaxMetaspaceSize=N 指用于限制Metaspace增長的上限,防止因為某些情況導致Metaspace無限的使用本地內存聪姿。
- 不管兩個參數(shù)如何設置碴萧,都會從20.8M開始,然后隨著類加載越來越多不斷擴容調整直到最大末购。
- 查看大小 jstat -gc pid MC: current metaspace capacity MU: mateaspace utilization 單位是KB破喻。