1. 程式人生 > >Java8 第五章

Java8 第五章

包含 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 第五章