Java 8系列之StreamApi
阿新 • • 發佈:2018-12-03
Stream的三個操作步驟
1.建立Stream
2.中間操作
3.終止操作
1.建立Stream
@Test
public void creatStream(){
//1.通過Collection系列集合提供的stream()或者parallelStream();
List<String> list=new ArrayList<String>();
Stream<String> stream1 = list.stream();
//2.通過Arrays中的靜態方法Stream()獲取陣列流
Integer[] ints=new Integer[10];
Stream<Integer> stream2 = Arrays.stream(ints);
//3.通過Stream類中的靜態方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
Stream<Object> empty = Stream.empty();
//4.建立無限流
//迭代
Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
//生成
Stream<Double> stream5 = Stream.generate(() -> Math.random());
}
2.中間操作
建立一個Student類用來做測試
public class Student {
private String name;
private int age;
private int score;
...
private Status status;
public enum Status{
Free,Busy,Vocation
}
}
List<Student> students=Arrays.asList(
new Student("mm",22,78,Student.Status.Busy),
new Student("kk",23,98,Student.Status.Free),
new Student("qq",21,56,Student.Status.Vocation),
new Student("hh",23,43,Student.Status.Busy),
new Student("hh",23,43,Student.Status.Busy)
);
中間操作–篩選和切片
/**
* 中間操作--篩選和切片
*/
@Test
public void middle_(){
//filer:過濾 Stream<T> filter(Predicate<? super T> predicate);
System.out.println("-------------------------------------------");
Stream<Student> filer = students.stream().filter(s -> s.getScore() > 60);
filer.forEach(System.out::println);
//limit:截斷
System.out.println("-------------------------------------------");
Stream<Student> limit = students.stream().limit(2);
limit.forEach(System.out::println);
//skip:跳過
System.out.println("-------------------------------------------");
Stream<Student> skip = students.stream().skip(2);
skip.forEach(System.out::println);
//distinct:去重,通過流所生成元素的hashCode()和equals()去除重複的元素(也就是說Student要重寫hashCode()和equals())
System.out.println("-------------------------------------------");
Stream<Student> distinct = students.stream().distinct();
distinct.forEach(System.out::println);
//peek:檢視Stream流水線中的資料流的值
System.out.println("-------------------------------------------");
Stream<Integer> peek = students.stream().map(o->o.getScore()).peek(o-> System.out.print("原分數:"+o)).map(o->o+20);
peek.forEach(o-> System.out.println(",新分數:"+o));
}
中間操作–對映
/**
* 中間操作--對映
*/
@Test
public void middle_map(){
//map:對映,引數為Function<? super T, ? extends R> mapper
System.out.println("-------------------------------------------");
Stream<String> map= students.stream().map(Student::getName);
map.forEach(System.out::println);
//flatmap:對映,引數為Function<? super T, ? extends Stream<? extends R>> mapper,將Function方法返回的每個流中的每個元素放到流中
//map與flatmap的區別像是list的add()與addAll(),當然也不完全類似
System.out.println("-------------------------------------------");
Stream<Character> flatMap = students.stream().flatMap(s -> toBeCharacter(s.getName()));
flatMap.forEach(System.out::print);
//進一步學習map和flatmap
String[] arrayOfWords = {"Goodbye", "World"};
Stream<String> words = Arrays.stream(arrayOfWords);
//map(Arrays::stream)得到的是一個流的列表
List<Stream<String>> map1 = words.map(word -> word.split(""))
.map(Arrays::stream)
.distinct()
.collect(toList());
System.out.println("---------------------------------------map1:"+map1.get(0).collect(toList())+","+map1.get(1).collect(toList()));
//流只能消費一次,所以words已經被消費了,需要重複建立
Stream<String> words1 = Arrays.stream(arrayOfWords);
//各個陣列並不是分別對映成一個流,而是對映成流的內容
List<String> flatMap1 = words1.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(toList());
System.out.println("---------------------------------------flatMap1:"+flatMap1);
}
public static Stream<Character> toBeCharacter(String str){
List<Character> list=new ArrayList<>();
for (Character c:str.toCharArray()){
list.add(c);
}
return list.stream();
}
中間操作–排序
/**
* 中間操作--排序
*/
@Test
public void middle_sort(){
//sorted():排序,陣列中的物件需要實現Comparable
//sorted(Comparator<? super T> comparator):排序,通過Comparator定製排序
Stream<Student> sorted = students.stream().sorted((x, y) -> Integer.compare(x.getAge(), y.getAge()));
sorted.forEach(System.out ::println);
}
2.終止操作
終止操作–查詢與匹配
/**
* 終止操作--查詢與匹配
*/
@Test
public void end_match_find(){
//allMatch:檢查是否匹配所有元素
boolean allMatch = students.stream().allMatch(s -> s.getStatus().equals(Student.Status.Busy));
System.out.println("是否所有人都很忙:"+allMatch);
//anyMatch:檢查是否匹配一個元素
boolean anyMatch = students.stream().anyMatch(s -> s.getStatus().equals(Student.Status.Busy));
System.out.println("是否有人很忙:"+anyMatch);
//noneMatch:檢查是否沒有匹配所有元素
boolean noneMatch = students.stream().noneMatch(s -> s.getStatus().equals(Student.Status.Busy));
System.out.println("是否所有人都很閒:"+noneMatch);
//findFirst:返回第一個元素
Optional<Student> first = students.stream().findFirst();
System.out.println("第一個元素:"+first.get());
//findAny:返回當前流中的任意元素
Optional<Student> any = students.parallelStream().filter(s -> s.getStatus().equals(Student.Status.Busy)).findAny();
System.out.println("任一個元素:"+any.get());
}
終止操作–統計
/**
* 終止操作--統計
*/
@Test
public void end_Statistics(){
//count:返回流中元素的總個數
long count = students.stream().count();
System.out.println("學生人數:"+count);
//max:返回流中最大值
Optional<Student> max = students.stream().max((x, y) -> Integer.compare(x.getScore(), y.getScore()));
System.out.println("分數最高的學生:"+max.get());
//min:返回流中最小值
Optional<Integer> min = students.stream().map(Student::getScore).min(Integer::compare);
System.out.println("最低分數"+min.get());
//sum(),實際是沒有這個方法的,因為無法對stream<T>中的T可能並不是數值,無法對它做控制,解決方式如下
//引入數值流,注意mapToInt()返回的物件是IntStream,不是stream<T>
IntStream intStream = students.stream().mapToInt(Student::getScore);
System.out.println("總分數"+intStream.sum());
//將IntStream轉為stream<T>,使用boxed()方法
// Stream<Integer> stream = intStream.boxed();
}
終止操作–歸約
/**
* 終止操作--歸約
*/
@Test
public void end_reduce(){
//reduce:歸約,元素計算
//第一種,有初始值:T reduce(T identity, BinaryOperator<T> accumulator);
Integer reduce = students.stream().map(s -> s.getScore()).reduce(0, (x, y) -> x + y);
System.out.println("分數總和:"+reduce);
//第二種,無初始值:Optional<T> reduce(BinaryOperator<T> accumulator);可能為空,所以返回Optional
Optional<Integer> reduce1 = students.stream().map(s -> s.getScore()).reduce((x, y) -> x + y);
System.out.println("分數總和:"+reduce1.get());
Stream<Integer> stream = Arrays.stream(new Integer[2]);
//Optional<Integer> reduce2 = stream.reduce((x, y) -> x + y);
//System.out.println("結果是否為空:"+reduce2.isPresent());
//求最大值,最小值
Optional<Integer> maxOptional = students.stream().map(s -> s.getScore()).reduce(Integer::max);
System.out.println("最大值 :"+maxOptional.get());
}
終止操作–收集
/**
* 終止操作--收集
*/
@Test
public void end_collect(){
//collection:收集,給stream中的元素做彙總,引數Collector<? super T, A, R> collector
System.out.println("----------------------------list------------------------------");
List<String> list = students.stream().map(s -> s.getName()).collect(toList());
list.forEach(System.out::println);
System.out.println("-------------------------set---------------------------------");
Set<String> set = students.stream().map(s -> s.getName()).collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("------------------------hashSet----------------------------------");
HashSet<String> hashSet = students.stream().map(s -> s.getName()).collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);
System.out.println("------------------------map----------------------------------");
Map<String, Student> map = students.stream().collect(Collectors.toMap(Student::getName, e -> e,(e1,e2)->e1));
for(String s:map.keySet()){
System.out.println(map.get(s));
}
}
終止操作–收集–groupingBy
/**
* 終止操作--收集--groupingBy
*/
@Test
public void end_collectors_groupingBy(){
//分組
System.out.println("---------------------原始寫法-------group by------------------------------");
Map<Student.Status, List<Student>> group1=new HashMap<Student.Status, List<Student>>();
for(Student s: students){
Student.Status status = s.getStatus();
List<Student> students = group1.get(status);
if(students==null){
students=new ArrayList<Student>();
group1.put(s.getStatus(),students);
}
students.add(s);
}
for (Student.Status s:group1.keySet()){
System.out.println(s+":"+group1.get(s)