java8 的forEach、filter、map、distinct、sorted、peek、limit、skip、count、anyMatch、allMatch、noneMatch、toArray操作、min、max、findFirst、findAny、reduce、collect操作 示例說明
package com.zpy.demo.java8;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @Author: Administrator
* @Description:
* @Date:Create:in 2019/10/16 15:53
*/
public class LambdaDemo {
public static void main(String[] args){
List<Person> p1=getPersonList();
/**
* 遍歷
void forEach(Consumer<? super T> action);
void forEachOrdered(Consumer<? super T> action)
*/
List<String> strsss = Arrays.asList("a", "b", "c");
strsss.stream().forEachOrdered(System.out::print);//abc
strsss.stream().forEach(System.out::print);//abc
strsss.parallelStream().forEachOrdered(System.out::print);//abc
strsss.parallelStream().forEach(System.out::print);//bca
//先看第一段輸出和第二段輸出,使用的是stream的流,這個是一個串行流,也就是程序是串行執行的,所有看到遍歷的結果都是按照集合的元素放入的順序;
//看第三段和第四段輸出,使用的parallelStream的流,這個流表示一個並行流,也就是在程序內部迭代的時候,會幫你免費的並行處理
//第三段代碼的forEachOrdered表示嚴格按照順序取數據,forEach在並行中,隨機排列了;這個也可以看出來,在並行的程序中,如果對處理之後的數據,沒有順序的要求,使用forEach的效率,肯定是要更好的
/**
* 按條件過濾
* Stream<T> filter(Predicate<? super T> predicate);
* 這個方法,傳入一個Predicate的函數接口,這個接口傳入一個泛型參數T,做完操作之後,返回一個boolean值;filter方法的作用,
* 是對這個boolean做判斷,返回true判斷之後的對象,下面一個案例,可以看到怎麼使用
*/
//Predicate 接口定義 可以用作判斷使用
Predicate<Person> predicate = x -> x.getAge() > 5;//判斷年齡是否大於5
boolean boo=predicate.test(p1.get(1));
// 字符串的非空判斷
Predicate<String> predicateStr = x -> null == x || "".equals(x);
System.out.println(predicateStr.test(""));//true
//過濾年齡大於5的person 返回list
List<Person> personList=p1.stream().filter(predicate).collect(Collectors.toList());
List<Person> personList2=p1.stream().filter(person -> person.getAge()>5).collect(Collectors.toList());
/**
* map 類型轉換
* <R> Stream<R> map(Function<? super T, ? extends R> mapper);
* 這個方法傳入一個Function的函數式接口,這個接口,接收一個泛型T,返回泛型R,map函數的定義,返回的流,表示的泛型是R對象,
* 這個表示,調用這個函數後,可以改變返回的類型,先看下面的案例
*/
Function<Integer, String> function1 = x -> x +"www";//x爲傳入參數int類型 將它鏈接一個字符串 返回String類型
String zw=function1.apply(5);//結果 5www
//將p1中的年齡提取出來成一個list
List<Integer> ages=p1.stream().map(person -> person.getAge()).collect(Collectors.toList());
/**
* flatMap操作
* <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
* 這個接口,跟map一樣,接收一個Fucntion的函數式接口,不同的是,Function接收的泛型參數,第二個參數是一個Stream流;方法,
* 返回的也是泛型R,具體的作用是把兩個流,變成一個流返回,下面,我們看一個案例,來詳細解答,怎麼把兩個流的內容,
* 變成一個流的內容
*/
String[] strss = { "aaa", "bbb","ccc" };
Arrays.stream(strss).map(str -> str.split("")).forEach(System.out::println);// java.lang.String;@53d8d10a
List<String > w2=Arrays.stream(strss).map(str -> str.split("")).flatMap(Arrays::stream).collect(Collectors.toList());// aaabbbccc
Arrays.stream(strss).map(str -> str.split("")).flatMap(str -> Arrays.stream(str)).forEach(System.out::println);// aaabbbccc
/**
* 去重複
Stream<T> distinct();
*/
//去重複後輸出
p1.stream().distinct().forEach(System.out::println);
/**
* 排序
Stream<T> sorted();
根據屬性排序
Stream<T> sorted(Comparator<? super T> comparator);
*/
//排序 按person 中的age屬性排序
p1.stream().sorted((p0,p2)->p0.getAge()-p2.getAge()).forEach(System.out::println);
p1.stream().sorted(Comparator.comparing(person -> person.getAge())).forEach(System.out::println);
p1.stream().sorted(Comparator.comparing(Person::getAge)).forEach(System.out::println);
/**
* 對對象的屬性進行操作
Stream<T> peek(Consumer<? super T> action);
*/
//對對像進行操作 把年齡大於2的人的名字加上 青年
//p1.stream().filter(person -> person.getAge()>2).peek(person -> person.setName("青年"+person.getName())).forEach(System.out::println);
/**
* 截斷--取先maxSize個對象
Stream<T> limit(long maxSize);
截斷--忽略前N個對象
Stream<T> skip(long n);
*/
//截斷--取先maxSize個對象
p1.stream().limit(2).forEach(System.out::println);
//截斷--忽略前N個對象
p1.stream().skip(2).forEach(System.out::println);
/**
long count();
count方法,跟List接口的size一樣,返回的都是這個集合流的元素的長度,不同的是,流是集合的一個高級工廠,
中間操作是工廠裏的每一道工序,我們對這個流操作完成後,可以進行元素的數量的和;
boolean anyMatch(Predicate<? super T> predicate);
boolean allMatch(Predicate<? super T> predicate);
boolean noneMatch(Predicate<? super T> predicate);
剩下的三個方法,傳入的都是Predicate的函數式接口
anyMatch表示,判斷的條件裏,任意一個元素成功,返回true
allMatch表示,判斷條件裏的元素,所有的都是,返回true
noneMatch跟allMatch相反,判斷條件裏的元素,所有的都不是,返回true
*/
//統計有幾個年齡==10的人
long cou=p1.stream().filter(person -> person.getAge()==10).count();
//判斷list中是否有年齡==2的person
boolean si= p1.stream().anyMatch(person -> person.getAge()==2);//true
//判斷list中是否有所有人年齡==2
boolean si2= p1.stream().allMatch(person -> person.getAge()==2);//false
//判斷list中是否有所有人年齡==2
boolean si3= p1.stream().noneMatch(person -> person.getAge()==2);//false
/**
* 終端操作 toArray操作
* public final <A> A[] toArray(IntFunction<A[]> generator)
*/
List<String> st = Arrays.asList("a", "b", "c");
String[] dd = st.stream().toArray(str -> new String[st.size()]);
String[] dd1 = st.stream().toArray(String[]::new);
Object[] obj = st.stream().toArray();
String[] dd2 = st.toArray(new String[st.size()]);
Object[] obj1 = st.toArray();
//可以看到,前三個,是調用的stream的toArray的函數,以及一些用法,後面的兩個,是直接調用的List接口的toArray函數,List接口裏的
/**
* 終端操作 min,max,findFirst,findAny操作
Optional<T> min(Comparator<? super T> comparator); //集合中的最小值
Optional<T> max(Comparator<? super T> comparator); //集合中的最大值
Optional<T> findFirst(); //返回集合中的第一個
Optional<T> findAny(); //返回這個集合中,取到的任何一個對象
*/
//Optional的get方法,是取到操作後的對象,
List<Integer> integerList = Arrays.asList(1,5,8,3,9);
//Optional min=integerList.stream().min((o1,o2)-> o1.compareTo(o2));
Optional min=integerList.stream().min(Comparator.naturalOrder());
Optional max=integerList.stream().max((o1,o2)-> o1.compareTo(o2));
System.out.println("最小值"+min.get()+" 最大值-- "+max.get());
//查詢list中年齡最小的person
Optional aaa= p1.stream().min(Comparator.comparing(person -> person.getAge()));
Person pmin=(Person)aaa.get();
List<String> stringss = Arrays.asList("d", "b", "a", "c", "a");
Optional<String> aa = stringss.stream().filter(str -> !str.equals("a")).findFirst();
Optional<String> bb = stringss.stream().filter(str -> !str.equals("a")).findAny();
Optional<String> aa1 = stringss.parallelStream().filter(str -> !str.equals("a")).findFirst();
Optional<String> bb1 = stringss.parallelStream().filter(str -> !str.equals("a")).findAny();
System.out.println(aa.get() + "===" + bb.get());// d===d
System.out.println(aa1.get() + "===" + bb1.get());// d===b or d===c
/**
*終端操作reduce操作
* reduce 是一種歸約操作,將流歸約成一個值的操作叫做歸約操作,用函數式編程語言的術語來說,這種稱爲摺疊(fold);
T reduce(T identity, BinaryOperator<T> accumulator);
這個函數,接受2個參數,第一個表示初始值,第二個值,傳入的是一個函數式接口BinaryOperator,這個接口繼承BiFunction;計算的表達式的規則;
Optional<T> reduce(BinaryOperator<T> accumulator);
這個接口。只用傳入計算規則,初始值是list的第一個參數,返回的optional對象,預防list裏,全部是null;
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
*/
Integer hc = integerList.stream().reduce(0, (a, b) -> a + b);//求和 identity 初始值
Optional<Integer> hc1 = integerList.stream().reduce((a, b) -> a + b);//求和
Optional<Integer> hc11 = integerList.stream().reduce((a, b) -> a * b);//求乘積
System.out.println(hc);
System.out.println(hc1.get());
/**
* 終端操作 collect操作
* <R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
第一個,是傳入3個參數的抽象方法,
第二個只有一個參數的先看下stream中的collect操作Collectors靜態工廠類,而在這個靜態工廠類中,大部分的實現,
都是調用的三個參數的方法,幾乎滿足了我們日常中所有的操作;所以說,我們只看下,這個靜態工廠類中,有哪些實現
*/
//轉list
List<String> nameList = p1.stream().map(p -> p.getName()).collect(Collectors.toList());
//轉set
Set<String> nameSet = p1.stream().map(p -> p.getName()).collect(Collectors.toSet());
// 轉map,需要指定key和value,Function.identity()表示當前的Emp對象本身 原list中指定爲key的字段不能有重複
Map<Integer,Person> personMap=p1.stream().collect(Collectors.toMap(p->p.getAge(),Function.identity()));
//// 計算元素中的個數
Long count = p1.stream().collect(Collectors.counting());
// 數據求和 summingInt summingLong,summingDouble
Integer sumAges = p1.stream().collect(Collectors.summingInt(Person::getAge));//Person::getAge 等價於p->p.getAge()
// 平均值 averagingInt,averagingDouble,averagingLong
Double aveAges = p1.stream().collect(Collectors.averagingInt(Person::getAge));
// 綜合處理的,求最大值,最小值,平均值,求和操作
// summarizingInt,summarizingLong,summarizingDouble
IntSummaryStatistics intSummary = p1.stream().collect(Collectors.summarizingInt(Person::getAge));
System.out.println(intSummary.getAverage());//
System.out.println(intSummary.getMax());//
System.out.println(intSummary.getMin());//
System.out.println(intSummary.getSum());//
/**
* IntSummaryStatistics
*/
IntSummaryStatistics stats=p1.stream().mapToInt(x->x.getAge()).summaryStatistics();
System.out.println("列表中最大的數 : " + stats.getMax());
System.out.println("列表中最小的數 : " + stats.getMin());
System.out.println("所有數之和 : " + stats.getSum());
System.out.println("平均數 : " + stats.getAverage());
// 連接字符串,當然也可以使用重載的方法,加上一些前綴,後綴和中間分隔符
String strEmp = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining());
String strEmp1 = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中間的分隔符-"));
String strEmp2 = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中間的分隔符-", "前綴*", "&後綴"));
// maxBy 按照比較器中的比較結果刷選 最大值
Optional<Integer> maxAge = p1.stream().map(emp -> emp.getAge())
.collect(Collectors.maxBy(Comparator.comparing(Function.identity())));
// 最小值
Optional<Integer> minAge = p1.stream().map(emp -> emp.getAge())
.collect(Collectors.minBy(Comparator.comparing(Function.identity())));
System.out.println("max:" + maxAge);
System.out.println("min:" + minAge);
// 歸約操作 求和
Optional ot=p1.stream().map(emp -> emp.getAge()).collect(Collectors.reducing((x, y) -> x+ y));
int rr=p1.stream().map(emp -> emp.getAge()).collect(Collectors.reducing(0, (x, y) -> x + y));
List<Person> dq=new ArrayList();
dq.add(new Person("廣州",10));
dq.add(new Person("廣州",10));
dq.add(new Person("北京",7));
dq.add(new Person("北京",5));
dq.add(new Person("武漢",6));
dq.add(new Person("杭州",8));
dq.add(new Person("上海",3));
// 分操作 groupingBy 根據姓名,把原list進行分組
Map<String, List<Person>> mapGroup = dq.stream().collect(Collectors.groupingBy(Person::getName));
// partitioningBy 分區操作 需要根據類型指定判斷分區
Map<Boolean, List<Integer>> partitioningMap = p1.stream().map(emp -> emp.getAge())
.collect(Collectors.partitioningBy(age -> age > 5));
System.out.println("");
}
private static List<Person> getPersonList(){
List<Person> p=new ArrayList<>();
Person rr=new Person("兒子2",10);
Person rr1=new Person("兒子2",10);
p.add(rr);
//p.add(rr1);
for (int i=0;i<8;i++){
Person person=new Person("兒子"+i,i);
p.add(person);
}
return p;
}
}