用Stream來優(yōu)化老代碼,瞬間干凈優(yōu)雅了!
01 流如何簡化代碼
篩選出卡路里小于 400 的菜肴 對篩選出的菜肴進行一個排序 獲取排序后菜肴的名字
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.對篩選出的菜肴進行排序
????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ù)卡路里進行排序
????????????.map(Dish::getName)?//提取菜肴名稱
????????????.collect(Collectors.toList());?//轉(zhuǎn)換為List
}
對數(shù)據(jù)庫查詢到的菜肴根據(jù)菜肴種類進行分類,返回一個? Map?的結果
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)換成對應的數(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?方法進行條件篩選,filter?的方法參數(shù)為一個條件List ?integerList?=?Arrays.asList(1,?1,?2,?3,?4,?5);
Stream?stream?=?integerList.stream().distinct();
distinct?方法快速去除重復的元素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?方法跳過流中的元素,上述例子跳過前兩個元素,所以打印結果為 2,3,4,5,skip?的參數(shù)值必須 >=0,否則將會拋出異常List ?stringList?=?Arrays.asList("Java?8",?"Lambdas",?"In",?"Action");
Stream?stream?=?stringList.stream().map(String::length);
復制代碼
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?隨機查找一個List ?integerList?=?Arrays.asList(1,?2,?3,?4,?5);
Optional?result?=?integerList.stream().filter(i?->?i?>?3).findAny();
findAny?方法查找到其中一個大于三的元素并打印,因為內(nèi)部進行優(yōu)化的原因,當找到第一個滿足大于三的元素時就結束,該方法結果和?findFirst?方法結果一樣。提供?findAny?方法是為了更好的利用并行流,findFirst?方法在并行上限制更多int?sum?=?0;
for?(int?i?:?integerList)?{
sum?+=?i;
}
reduce?進行處理int?sum?=?integerList.stream().reduce(0,?(a,?b)?->?(a?+?b));
int?sum?=?integerList.stream().reduce(0,?Integer::sum);
reduce?接受兩個參數(shù),一個初始值這里是 0,一個?BinaryOperator accumulator?來將兩個元素結合起來產(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);
復制代碼
07 總結
最近熱文閱讀:
1、延時任務實現(xiàn)方案 2、服務端如何防止重復支付 3、五年工作經(jīng)驗總結 16 條的代碼規(guī)范 4、為什么我勸你放棄了Restful API? 5、Java8 Stream:2萬字20個實例,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合 6、公司規(guī)定所有接口都用 POST請求,這是為什么? 7、為什么阿里強制 boolean 類型變量不能使用 is 開頭? 8、面試官:InnoDB中一棵B+樹可以存放多少行數(shù)據(jù)? 9、MyBatis批量插入幾千條數(shù)據(jù),請慎用foreach 10、有了 for (;;) ,為什么還需要while (true) ?到底哪個更快? 關注公眾號,你想要的Java都在這里
評論
圖片
表情
