Java8 第五章
阿新 • • 發佈:2017-10-29
包含 fis lines pre col pairs 和equal box util
如果limit用在無序流比如源是Set會出現什麽??
GEOHASH??
Stream勾股數??
flatMap還是不是很明白
git merge master --allow-unrelated-histories
這個指令,可以強制把 無關聯的分支,merge過來?????
篩選和切片
-- filter ==> 接受一個謂詞(一個返回boolean的函數)作為參數,並返回一個包括符合謂詞的元素的流.
-- distinct ==> 返回一個元素各異(根據流所生成元素的hashCode和equals方法實現)的流.
==> 就是去重說的那麽費勁.
List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,4);
numbers.stream().filter(i->i % 2 ==0)
.distinct()
.forEach(System.out::println);
輸出:
2
4
-- 上面的numbers ==> 數值流(Stream<Integer>)
-- limit ( n ) ==> 返回一個不超過給定長度的流,如果流有序,則最多返回前n個元素.
--flatmap ==> (扁平化)方法讓你把一個流中的每個值都轉換成流,然後把所有的流連接起來成為一個流 .
--skip() ==>返回扔掉了前n個元素的流.
List<Dish> dishes = menu.stream().filter(d->d.getCalories()>300).skip(2).collect(toList()); //skip()
List<Dish> noSkipDishes = menu.stream().filter(d->d.getCalories()>300).collect(toList()); //謂詞篩選
List<Dish> firstSkipDish = menu.stream().skip(2).collect(toList()); //skip
List<Integer> map = menu.stream().map(Dish::getName).map(String::length).collect(toList());//對流中的每一個元素應用函數
小例子:
-- 給定列表[1,2,3] 和列表[3,4],返回 [(1,3),(1,4),(2,3),(2,4),(3,3),(3,4)]
List<Integer> numbers1 = Arrays.asList(1,2,3);
List<Integer> numbers2 = Arrays.asList(3,4);
List<int []> pairs = numbers1.stream.flatmap(i -> numbers2.stream
.map(j -> new int[]{i,j})).collect(toList());
-- 拓展前一個例子,只返回綜合能被三整除的數對.
List<Integer> numbers1 = Arrays.asList(1,2,3);
List<Integer> numbers2 = Arrays.asList(3,4);
List<int []> pairs = numbers1.stream.flatmap(i -> numbers2.stream
.filter(j -> (i+j) % 3 == 0)
.map(j -> new int[]{i,j})).collect(toList());
//numbers1.stream().flatMap(i -> numbers2.stream()
.map(jj -> Arrays.toString(new int[]{ i, jj }))).forEach(System.out::println);
-- anyMatch==>流中是否有一個元素能夠匹配給定的謂詞,返回boolean,是一個終端操作.
-- allMatch ==>流中是否所有元素都能夠匹配給定的謂詞,返回boolean,是一個終端操作 .
-- noneMatch ==>流中沒有任何元素與給定的謂詞匹配,返回boolean,是一個終端操作.
-- anyMatch allMatch和noneMatch這三個操作都用到了我們所謂的短路,這就是Java中&&和||運算符在流中的版本。
-- 短路==>操作不需要處理整個流就能得到結果,就像用and連接的大布爾表達式求值,不管表達式多長,
主要找到 一個表達式是false整個表達式就返回false.
-- findAny==>返回當前流中的任意元素.終端操作.可以配合其他流操作使用.
Optional<Dish> any = menu.stream().filter(x -> x.getCalories() > 300).findAny();
為什麽返回Optional?
Optional<T>類是一個容器類,代表一個值存在或者不存在.在上面的例子中findAny可能什麽元素都沒找到.
Optional中顯式的檢查值是否存在方法==>
isPresent( ) 將在Optional包含值的時候返回true,否則返回false.
ifPresent( Comsumer<T> block) 會在值存在的時候執行給定的代碼塊.
T get() 會在值存在的時候返回值,否則拋出NoSuchElement異常
T orElse(T other) 會在值存在的時候返回值,否則返回默認值.
-- findFirst()==>返回流中第一個元素
總結:
到目前為止所有的終端操作
- 返回一個boolean(allMatch之類)
- 返回void的(foreach等)
- 返回Optional對象(findAny等)
規約
reduce==>
- 有初始值 : 一個是初始值,一個是BinaryOperator<T>將兩個元素結合起來產生一個新值.
- 無初始值 : 無初始值時,因為有可能沒有元素為null嘛,所以設計的時候返回值為Optional<T>對象.
Optional<Integer> sum = numbers1.stream().reduce(Integer::sum); //無初始值
Integer sum1 = numbers1.stream().reduce(0, Integer::sum); //有初始值
Optional<Integer> max1 = numbers1.stream().reduce(Integer::max); //無初始值
Integer max2 = numbers1.stream().reduce(0, Integer::max); //有初始值
Optional<Integer> min1 = numbers1.stream().reduce(Integer::min); //無初始值
Integer min2 = numbers1.stream().reduce(0, Integer::min); //有初始值
//計算menu中一共多少個菜
int count = menu.stream().map(x->1).reduce(0,Integer::sum);
long count1 = (long) menu.size();
long count2 = menu.stream().count();
數值流
--原始類型特化==>防止來回裝箱和拆箱
--映射到數值流<==>轉換回對象流
- 將流轉換成特化版本 : mapToInt , mapToDouble , mapToLong.
int calories = menu.stream(). //返回一個Stream<Dish>
mapToInt(Dish::getCalories) //返回一個IntStream
.sum(); //
IntStream intStream = menu.stream().mapToInt(Dish::getCalories); //將Stream轉換為數值流
java.util.stream.Stream<Integer> stream1 = intStream.boxed(); //將數值流轉換成一般流(裝箱操作)
-- 默認值OptionalInt
OptionalInt max = menu.stream().mapToInt(Dish::getCalories).max();
int max4 = max.orElse(1); //如果沒有最大值,顯式提供一個默認的最大值.
-- 數值範圍
range和rangeClose的區別==>range不包含結束值
List<Integer> collect = IntStream.rangeClosed(1, 100).filter(n -> n % 2 == 0) //一個從1到100的偶數流
.boxed() //數值流轉化成一般流
.collect(Collectors.toList()); //轉化成list
-- 創建流
//創建流
//創建數組流
int[] numbers3 ={2,3,4,5,6,11,13};
int sum3 = Arrays.stream(numbers3).sum();
//由值創建流
Stream<String> stream22 = Stream.of("Java8","Lambda","In");
stream22.map(String::toUpperCase).forEach(System.out::println);
//由文件生成流 省略
System.out.println("-----------------------------------");
//創建無限流(一般在生成一系列值的時候應該使用iterate)
Stream.iterate(0,n->n+2).limit(10).forEach(System.out::println);
匯總
--查找流中的最大值(兩種情況)
//一個是值一個是對象,不一樣!
OptionalInt intStream1 = menu.stream().mapToInt(Dish::getCalories).max();//返回對象的熱量最大的那個值
Optional<Dish> collect1 = menu.stream().collect(maxBy(Comparator.comparing(Dish::getCalories)));//返回熱量最大的那個對象
自動提示轉換==>
Optional<Dish> max3 = menu.stream().max(Comparator.comparing(Dish::getCalories));//返回熱量最大的那個對象
--求和
Integer ccollect2 = menu.stream().mapToInt(Dish::getCalories).sum();
Integer collect2 = menu.stream().collect(summingInt(Dish::getCalories));
--求平均值
double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));
--通過工廠類(summarizingInt)
IntSummaryStatistics collect3 = menu.stream().collect(summarizingInt(Dish::getCalories));
double average = collect3.getAverage();
long count3 = collect3.getCount();
int max5 = collect3.getMax();
int min = collect3.getMin();
long sum2 = collect3.getSum();
-- 連接字符串
<wiz_code_mirror>
String collect4 = menu.stream().map(Dish::getName).collect(joining(","));
System.out.println(collect4);
輸出:
pork,beef,chicken,french fries,rice,season fruit,pizza,prawns,salmon
-- 分組
//一級分組(普通的groupingBy(f)<=實際是=>groupingBy(f,toList()))
Map<Dish.Type, List<Dish>> collect5 = menu.stream().collect(groupingBy(Dish::getType));
//一級分組
Map<CaloricLevel, List<Dish>> collect6 = menu.stream().collect(groupingBy(x -> {
if (x.getCalories() <= 400) return CaloricLevel.DIET;
else if (x.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}));
//二級分組
menu.stream().collect(groupingBy(Dish::getType, groupingBy(dish -> {
if (dish.getCalories() <= 300) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
})));
輸出:
{
MEAT={DIET=[chicken], NORMAL=[beef], FAT=[pork]},
FISH={DIET=[prawns], NORMAL=[salmon]},
OTHER={DIET=[rice, seasonal fruit], NORMAL=[french fries, pizza]}
}
?
?
//傳遞counting收集器作為groupingBy收集器的第二個參數
//collect7==> {MEAT=3, FISH=2, OTHER=4}
Map<Dish.Type, Long> collect7 = menu.stream().collect(groupingBy(Dish::getType, counting()));
//以Dish的類型作為鍵 ,以包裝了該類型中熱量最高的Dish的Optional<Dish>作為值,Optional沒有實際意義其實
//collect8==> {FISH=Optional[salmon], OTHER=Optional[pizza], MEAT=Optional[pork]}
Map<Dish.Type, Optional<Dish>> collect8 = menu.stream().collect(groupingBy(Dish::getType,
maxBy(Comparator.comparingInt(Dish::getCalories))));
//把收集器的結果轉換為另一種類型,使用Collectors.collectingAndThen工廠方法返回的收集器.
//這個工廠方法接受兩個參數——要轉換的收集器以及轉換函數,返回另一個收集器.
//collect9 ==> {FISH=salmon, OTHER=pizza, MEAT=pork}
Map<Dish.Type, Dish> collect10 = menu.stream().collect(groupingBy(Dish::getType,
collectingAndThen(maxBy(Comparator.comparingInt(Dish::getCalories)), Optional::get)));
?
Map<Dish.Type, Dish> collect9 = menu.stream().collect(Collectors.toMap(Dish::getType,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Dish::getCalories))));
?
Map<Dish.Type, IntSummaryStatistics> collect11 = menu.stream()
.collect(groupingBy(Dish::getType,
summarizingInt(Dish::getCalories)));
?
//groupingBy()和map()收集器搭配使用
//collect12==>{OTHER=[DIET, NORMAL], MEAT=[DIET, NORMAL, FAT], FISH=[DIET, NORMAL]}
Map<Dish.Type, Set<CaloricLevel>> collect12 =
menu.stream().collect(
groupingBy(Dish::getType, mapping(
dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT; },toCollection(HashSet::new))));
Map<Dish.Type, Set<CaloricLevel>> collect12 =
menu.stream().collect(
groupingBy(Dish::getType, mapping(
dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT; },toSet())));
-- 分區
//分區是分組的特殊情況: 由一個謂詞(返回一個布爾值)作為分類函數==>稱之為分區函數
//分區函數返回一個布爾值,意味著分組的Map的鍵類型是Boolean==>因此最多分兩組,true一組,false一組
//關鍵字:partitionBy 分區
//collect13
Map<Boolean, List<Dish>> collect13 = menu.stream().collect(partitioningBy(Dish::isVegetarian));
List<Dish> dishes1 = collect13.get(true);//找出所有素菜
Java8 第五章