用Stream來優(yōu)化老代碼,瞬間干凈優(yōu)雅了!
來源丨Java技術(shù)江湖
Java8 的新特性主要是 Lambda 表達(dá)式和流,當(dāng)流和 Lambda 表達(dá)式結(jié)合起來一起使用時,因為流申明式處理數(shù)據(jù)集合的特點(diǎn),可以讓代碼變得簡潔易讀。
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<String> beforeJava7(List<Dish> dishList) {
List<Dish> lowCaloricDishes = new ArrayList<>();
//1.篩選出卡路里小于400的菜肴
for (Dish dish : dishList) {
if (dish.getCalories() < 400) {
lowCaloricDishes.add(dish);
}
}
//2.對篩選出的菜肴進(jìn)行排序
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getCalories(), o2.getCalories());
}
});
//3.獲取排序后菜肴的名字
List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish d : lowCaloricDishes) {
lowCaloricDishesName.add(d.getName());
}
return lowCaloricDishesName;
}
private List<String> afterJava8(List<Dish> 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<Type, List>的結(jié)果
private static Map<Type, List<Dish>> beforeJDK8(List<Dish> dishList) {
Map<Type, List<Dish>> result = new HashMap<>();
for (Dish dish : dishList) {
//不存在則初始化
if (result.get(dish.getType())==null) {
List<Dish> dishes = new ArrayList<>();
dishes.add(dish);
result.put(dish.getType(), dishes);
} else {
//存在則追加
result.get(dish.getType()).add(dish);
}
}
return result;
}
private static Map<Type, List<Dish>> afterJDK8(List<Dish> dishList) {
return dishList.stream().collect(groupingBy(Dish::getType));
}
02 什么是流
03 如何生成流
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream();
int[] intArr = new int[]{1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(intArr);
Arrays.stream 方法生成流,并且該方法生成的流是數(shù)值流【即 IntStream 】而不是 Stream。補(bǔ)充一點(diǎn)使用數(shù)值流可以避免計算過程中拆箱裝箱,提高性能。
mapToInt、mapToDouble、mapToLong三種方式將對象流【即 Stream】轉(zhuǎn)換成對應(yīng)的數(shù)值流,同時提供了 boxed 方法將數(shù)值流轉(zhuǎn)換為對象流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
of 方法生成流,通過 Stream 的 empty 方法可以生成一個空流
Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5);
Stream<Double> stream = Stream.generate(Math::random).limit(5);
04 流的操作類型
中間操作
filter、map 等
終端操作
count、collect 等
05 流使用
中間操作
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream().filter(i -> i > 3);
filter 方法進(jìn)行條件篩選,filter 的方法參數(shù)為一個條件
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream().distinct();
distinct 方法快速去除重復(fù)的元素
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream().limit(3);
limit 方法指定返回流的個數(shù),limit 的參數(shù)值必須 >=0,否則將會拋出異常
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream().skip(2);
skip 方法跳過流中的元素,上述例子跳過前兩個元素,所以打印結(jié)果為 2,3,4,5,skip 的參數(shù)值必須 >=0,否則將會拋出異常
List<String> stringList = Arrays.asList("Java 8", "Lambdas", "In", "Action");
Stream<Integer> stream = stringList.stream().map(String::length);
復(fù)制代碼
map 方法可以完成映射,該例子完成中 String -> Integer 的映射,之前上面的例子通過 map 方法完成了 Dish->String 的映射
List<String> wordList = Arrays.asList("Hello", "World");
List<String> strList = wordList.stream()
.map(w -> w.split(" "))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
map(w -> w.split(" ")) 的返回值為 Stream<String[]>,我們想獲取 Stream,可以通過 flatMap 方法完成 Stream ->Stream 的轉(zhuǎn)換
allMatch 匹配所有
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
if (integerList.stream().allMatch(i -> i > 3)) {
System.out.println("值都大于3");
}
anyMatch 匹配其中一個
List<Integer> 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<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
if (integerList.stream().noneMatch(i -> i > 3)) {
System.out.println("值都小于3");
}
終端操作
count
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Long result = integerList.stream().count();
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Long result = integerList.stream().collect(counting());
findFirst 查找第一個
//查找到第一個大于 3 的元素并打印
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = integerList.stream().filter(i -> i > 3).findFirst();
findAny 隨機(jī)查找一個
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> 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<Integer> min = menu.stream().map(Dish::getCalories).min(Integer::compareTo);
Optional<Integer> 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> comparator
Optional<Integer> min = menu.stream().map(Dish::getCalories).collect(minBy(Integer::compareTo));
Optional<Integer> max = menu.stream().map(Dish::getCalories).collect(maxBy(Integer::compareTo));
minBy 獲取流中最小值,maxBy 獲取流中最大值,方法參數(shù)為 Comparator<? super T> comparator
reduce 獲取最小最大值
Optional<Integer> min = menu.stream().map(Dish::getCalories).reduce(Integer::min);
Optional<Integer> max = menu.stream().map(Dish::getCalories).reduce(Integer::max);
復(fù)制代碼
07 總結(jié)
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取
評論
圖片
表情
