用Stream來優(yōu)化老代碼,瞬間干凈優(yōu)雅了!
往期熱門文章: 2、自定義注解妙用,一行代碼搞定用戶操作日志記錄,你學(xué)會了嗎?
3、離開互聯(lián)網(wǎng)上岸1年后,我后悔了!重回大廠內(nèi)卷
5、我司Spring Boot 項目打包 + Shell 腳本部署詳細(xì)總結(jié),太有用了!
Java8 的新特性主要是 Lambda 表達(dá)式和流,當(dāng)流和 Lambda 表達(dá)式結(jié)合起來一起使用時,因為流申明式處理數(shù)據(jù)集合的特點,可以讓代碼變得簡潔易讀。
01 流如何簡化代碼
篩選出卡路里小于 400 的菜肴 對篩選出的菜肴進(jìn)行一個排序 獲取排序后菜肴的名字
Dish.java(菜肴)public?class?Dish?{
????private?String?name;
????private?boolean?vegetarian;
????private?int?calories;
????private?Type?type;
????//?getter?and?setter
}
private?List ?beforeJava7(List {?dishList) ?
????List?lowCaloricDishes?=?new?ArrayList<>();
????//1.篩選出卡路里小于400的菜肴
????for?(Dish?dish?:?dishList)?{
????????if?(dish.getCalories()?400)?{
????????????lowCaloricDishes.add(dish);
????????}
????}
????//2.對篩選出的菜肴進(jìn)行排序
????Collections.sort(lowCaloricDishes,?new?Comparator()?{
????????@Override
????????public?int?compare(Dish?o1,?Dish?o2)?{
????????????return?Integer.compare(o1.getCalories(),?o2.getCalories());
????????}
????});
????//3.獲取排序后菜肴的名字
????List?lowCaloricDishesName?=?new?ArrayList<>();
????for?(Dish?d?:?lowCaloricDishes)?{
????????lowCaloricDishesName.add(d.getName());
????}
????return?lowCaloricDishesName;
}
private?List ?afterJava8(List {?dishList) ?
????return?dishList.stream()
????????????.filter(d?->?d.getCalories()?400)?//篩選出卡路里小于400的菜肴
????????????.sorted(comparing(Dish::getCalories))?//根據(jù)卡路里進(jìn)行排序
????????????.map(Dish::getName)?//提取菜肴名稱
????????????.collect(Collectors.toList());?//轉(zhuǎn)換為List
}
對數(shù)據(jù)庫查詢到的菜肴根據(jù)菜肴種類進(jìn)行分類,返回一個? Map?的結(jié)果
private?static?Map >?beforeJDK8(List ?dishList)?{
????Map>?result?=?new?HashMap<>();
????for?(Dish?dish?:?dishList)?{
????????//不存在則初始化
????????if?(result.get(dish.getType())==null)?{
????????????List?dishes?=?new?ArrayList<>();
????????????dishes.add(dish);
????????????result.put(dish.getType(),?dishes);
????????}?else?{
????????????//存在則追加
????????????result.get(dish.getType()).add(dish);
????????}
????}
????return?result;
}
private?static?Map >?afterJDK8(List ?dishList)?{
????return?dishList.stream().collect(groupingBy(Dish::getType));
}
02 什么是流
03 如何生成流
List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream();
int[]?intArr?=?new?int[]{1,?2,?3,?4,?5};
IntStream?stream?=?Arrays.stream(intArr);
Arrays.stream?方法生成流,并且該方法生成的流是數(shù)值流【即?IntStream?】而不是 Stream。補充一點使用數(shù)值流可以避免計算過程中拆箱裝箱,提高性能。mapToInt、mapToDouble、mapToLong三種方式將對象流【即 Stream】轉(zhuǎn)換成對應(yīng)的數(shù)值流,同時提供了?boxed?方法將數(shù)值流轉(zhuǎn)換為對象流Stream ?stream?=?Stream.of(1,?2,?3,?4,?5);
of?方法生成流,通過 Stream 的?empty?方法可以生成一個空流Stream ?lines?=?Files.lines(Paths.get("data.txt"),?Charset.defaultCharset())
Stream ?stream?=?Stream.iterate(0,?n?->?n?+?2).limit(5);
Stream ?stream?=?Stream.generate(Math::random).limit(5);
04 流的操作類型
中間操作
filter、map?等終端操作
count、collect?等05 流使用
中間操作
List ?integerList?=?Arrays.asList(1,?1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream().filter(i?->?i?>?3);
filter?方法進(jìn)行條件篩選,filter?的方法參數(shù)為一個條件List ?integerList?=?Arrays.asList(1,?1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream().distinct();
distinct?方法快速去除重復(fù)的元素List ?integerList?=?Arrays.asList(1,?1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream().limit(3);
limit?方法指定返回流的個數(shù),limit 的參數(shù)值必須 >=0,否則將會拋出異常List ?integerList?=?Arrays.asList(1,?1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream().skip(2);
skip?方法跳過流中的元素,上述例子跳過前兩個元素,所以打印結(jié)果為 2,3,4,5,skip?的參數(shù)值必須 >=0,否則將會拋出異常List ?stringList?=?Arrays.asList("Java?8",?"Lambdas",?"In",?"Action");
Stream?stream?=?stringList.stream().map(String::length);
復(fù)制代碼
map?方法可以完成映射,該例子完成中?String -> Integer?的映射,之前上面的例子通過?map?方法完成了?Dish->String?的映射List ?wordList?=?Arrays.asList("Hello",?"World");
List?strList?=?wordList.stream()
????????.map(w?->?w.split("?"))
????????.flatMap(Arrays::stream)
????????.distinct()
????????.collect(Collectors.toList());
map(w -> w.split(" "))?的返回值為?Stream,我們想獲取?Stream,可以通過?flatMap?方法完成?Stream ->Stream?的轉(zhuǎn)換allMatch?匹配所有List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
if?(integerList.stream().allMatch(i?->?i?>?3))?{
????System.out.println("值都大于3");
}
anyMatch?匹配其中一個List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
if?(integerList.stream().anyMatch(i?->?i?>?3))?{
????System.out.println("存在大于3的值");
}
for?(Integer?i?:?integerList)?{
????if?(i?>?3)?{
????????System.out.println("存在大于3的值");
????????break;
????}
}
noneMatch?全部不匹配List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
if?(integerList.stream().noneMatch(i?->?i?>?3))?{
????System.out.println("值都小于3");
}
終端操作
countList ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Long?result?=?integerList.stream().count();
List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Long?result?=?integerList.stream().collect(counting());
findFirst?查找第一個//查找到第一個大于?3?的元素并打印
List?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Optional?result?=?integerList.stream().filter(i?->?i?>?3).findFirst();
findAny?隨機(jī)查找一個List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Optional?result?=?integerList.stream().filter(i?->?i?>?3).findAny();
findAny?方法查找到其中一個大于三的元素并打印,因為內(nèi)部進(jìn)行優(yōu)化的原因,當(dāng)找到第一個滿足大于三的元素時就結(jié)束,該方法結(jié)果和?findFirst?方法結(jié)果一樣。提供?findAny?方法是為了更好的利用并行流,findFirst?方法在并行上限制更多int?sum?=?0;
for?(int?i?:?integerList)?{
sum?+=?i;
}
reduce?進(jìn)行處理int?sum?=?integerList.stream().reduce(0,?(a,?b)?->?(a?+?b));
int?sum?=?integerList.stream().reduce(0,?Integer::sum);
reduce?接受兩個參數(shù),一個初始值這里是 0,一個?BinaryOperator accumulator?來將兩個元素結(jié)合起來產(chǎn)生一個新值,Optional ?min?=?menu.stream().map(Dish::getCalories).min(Integer::compareTo);
Optional?max?=?menu.stream().map(Dish::getCalories).max(Integer::compareTo);
OptionalInt?min?=?menu.stream().mapToInt(Dish::getCalories).min();
OptionalInt?max?=?menu.stream().mapToInt(Dish::getCalories).max();
min?獲取流中最小值,max?獲取流中最大值,方法參數(shù)為?Comparator super T> comparatorOptional ?min?=?menu.stream().map(Dish::getCalories).collect(minBy(Integer::compareTo));
Optional?max?=?menu.stream().map(Dish::getCalories).collect(maxBy(Integer::compareTo));
minBy?獲取流中最小值,maxBy?獲取流中最大值,方法參數(shù)為?Comparator super T> comparatorreduce?獲取最小最大值Optional ?min?=?menu.stream().map(Dish::getCalories).reduce(Integer::min);
Optional?max?=?menu.stream().map(Dish::getCalories).reduce(Integer::max);
復(fù)制代碼
07 總結(jié)
往期熱門文章:
1、《歷史文章分類導(dǎo)讀列表!精選優(yōu)秀博文都在這里了!》 2、程序員裸辭全職接單一個月的感觸 3、Java8 Stream:2萬字20個實例,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合 4、字節(jié)終面:兩個文件的公共URL怎么找? 5、留在一線,逃離一線?我從上海舉家回成都的生活經(jīng)歷告訴你 6、公司規(guī)定所有接口都用 POST請求,這是為什么? 7、我被這個瀏覽了 746000 次的問題驚住了! 8、騰訊三面:40億個QQ號碼如何去重? 9、自從用完Gradle后,有點嫌棄Maven了!速度賊快! 10、一個員工的離職成本有多恐怖!
評論
圖片
表情
