初识Stream
Stream使用的对象
Steam是Java8以后的语法糖,用于某些匿名内部类的简化,是函数式编程的重要体现,重点关注于数据的操作流程,是非常成功的一个。
Stream的主要适用对象就是Arrays,集合类(List,Set,Stack,Queue)和Map的使用,能够解脱复杂的遍历循环以及对象的创建,使数据的处理更流程化
-Array的区别
public static void filterFunc() {
int[] arrayAlpha = new int[]{1, 2, 44, 30, 23, 101};
// NOTE 筛选大于30的数字因为数组的长度在定义的时候已经不可改变,所以进行筛选就显得有点麻烦
List<Integer> list = new ArrayList<>();
for (int index = 0; index < arrayAlpha.length; index++) {
if (arrayAlpha[index] > 30) {
list.add((Integer) arrayAlpha[index]);
}
}
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
Arrays.stream(result).forEach(System.out::println);
}
上面进行写起来代码量很大,如果使用stream来进行处理就是一行代码就能解决!!!
int [] arrayRes=Arrays.stream(arrayAlpha).filter(ele->ele>30).toArray();
Arrays.stream(arrayRes).forEach(System.out::print);
- List ,Set,Stack,Queue,Map,Stream也是会简单很多
List<Integer>listAlpha=new ArrayList<>(List.of(1,2,6,9,4,109));
List<Integer>listAlphaResult=listAlpha.stream().filter(ele->ele>5).collect(Collectors.toList());
// List<Integer> tempResult = new ArrayList<>();
// for (Integer ele : listAlpha) {
// if (ele > 5) {
// tempResult.add(ele);
// }
// }
System.out.println(listAlphaResult);
Set<String> setAlpha=new HashSet<>(List.of("alpha","beta","gamma","ph"));
Set<String>setAlphaResult=setAlpha.stream().filter(ele->ele.contains("a")).collect(Collectors.toSet());
// Set<String>stringSetRes=new HashSet<>();
// for(String ele:setAlpha){
// if (ele.contains("ph")){
// stringSetRes.add(ele);
// }
// }
System.out.println(setAlphaResult);
Map<String,Integer> mapAlpha=new HashMap<>();
mapAlpha.put("alpha",1);
mapAlpha.put("beta",13);
mapAlpha.put("gamma",19);
// Map<String,Integer>mapAlphaResult=mapAlpha.stream
Stream<Map.Entry<String,Integer>> stream=mapAlpha.entrySet().stream();
Map<String,Integer>streamResult=stream.filter(ele->ele.getValue()>2)
.collect(Collectors.toMap(ele->ele.getKey(),ele-> ele.getValue()));
// Map<String,Integer> mapAlphaResult=new HashMap<>();
// for(Map.Entry<String ,Integer> entry:mapAlpha.entrySet()){
// if(entry.getValue()>10){
// mapAlphaResult.put(entry.getKey(),entry.getValue());
// }
// }
// System.out.println(mapAlphaResult);
System.out.println(streamResult);
//NOTE queue&stack
Queue<String>stringQueue=new LinkedList<>();
stringQueue.add("alpha");
stringQueue.add("beta");
stringQueue.add("gamma");
stringQueue.add("alpha");
List<String> alpha = stringQueue.stream().filter(ele -> ele.contains("alpha")).collect(Collectors.toList());
System.out.println(alpha);
Stack<String> stringStack=new Stack<>();
stringStack.add("alpha");
stringStack.add("beta");
stringStack.add("gamma");
stringStack.add("alpha");
List<String> beta = stringStack.stream().filter(ele -> ele.equals("gamma")).collect(Collectors.toList());
System.out.println(beta);
所以从上面的例子里可以看出来使用stream的简洁,而且代码的可读性非常好,有点像pipline一个阶段一个阶段执行,然后收集结果。
Stream的构成
- 逻辑结构图
stream就是这样的一个结构,构建—>操作—>结果收集。
-stream的创建
Array,collection(List,Set,Queue,Stack),Map都是支持stream来处理的。
-stream的转换
filter()、map()、distinct()、sorted()、limit()、skip()、flatMap()
-stream的终止
Steam的创建—开始管道
这个就是前面所讲的,stream的使用范围
Stream的转换—中间管道
getAuthors()初始化Author的List,
- filter()
对Author的List获取元素(对象)的Name 的String>3
List<Author> authorList = getAuthors();
List<Author> authorRes = authorList.stream()
.filter(ele -> ele.getName().length() > 3)
.collect(Collectors.toList());
- map()
拿到Author的name,然后处理以后的List,
重新建立一个Author的List
List<Author> authorList = getAuthors();
List<String> result = authorList.stream()
.map(new Function<Author, String>() {
@Override
public String apply(Author author) {
return "-" + author.getName() + "-";
}
})
.collect(Collectors.toList());
List<String> resultAlpha = authorList.stream().map(ele -> "start->" + ele.getName() + "<-end").collect(Collectors.toList());
System.out.println(resultAlpha);
List<Integer> resultBeta = authorList.stream()
.map(ele -> ele.getAge())
.collect(Collectors.toList());
List<Author> resultGamma = authorList.stream()
.map(ele -> new Author(ele.getName(), ele.getId(), ele.getAge() + 111, ele.getScore(), ele.getIntro(), null))
.collect(Collectors.toList());
System.out.println(resultGamma);
- distinct()
去除重复Name的List
List<Author> authorList = getAuthors();
// System.out.println(authorList);
List<String> distinctAuthorName = authorList.stream()
.map(author -> author.getName())
.distinct().collect(Collectors.toList());
- sorted()
这里就跟前面一篇文章写的三种排列,1、stream两个object.attribute进行对比
2、sorted(Comparator.comparing(object->object.attribute属性))3、实现implement Compareable接口的CompareTo
List<Author> sortedAuthors = authors.stream()
.sorted((o1, o2) -> o1.getAge() - o2.getAge())
.collect(Collectors.toList());
System.out.println(sortedAuthors);
List<Author> sortedAuthors2 = authors.stream().sorted(Comparator.comparing(author -> author.getAge())).collect(Collectors.toList());
System.out.println(sortedAuthors2);
List<Author> authors1 = getAuthors();
List<Author> authorsRes = authors1.stream().sorted().collect(Collectors.toList());
- limit()
选前几
List<Author> authors = getAuthors();
List<Author> authorsLimit = authors.stream().sorted().limit(2).collect(Collectors.toList());
System.out.println(authorsLimit);
- skip()
跳过前几
List<Author> authors = getAuthors();
/**获取最大年龄的*/
List<Author> skipResult = authors.stream().sorted().skip(1).collect(Collectors.toList());
System.out.println(skipResult);
- flatMap()
这是一个将stream()后的元素创建新的stream()
List authorList=…,其中Author的bookList元素也是一个List()
/**这个就是stream的元素然后形成新的stream*/
List<Author> fullAuthor = getFullAuthor();
// System.out.println(fullAuthor);
List<Book> bookList = fullAuthor.stream().flatMap(author -> author.getBooks().stream()).collect(Collectors.toList());
System.out.println(bookList);
List<String> bookCategoryList = bookList.stream()
.flatMap(book -> Arrays.stream(book.getCategory().split(",")))
.distinct().collect(Collectors.toList());
System.out.println(bookCategoryList.size());
Steam的终止—关闭管道
- forEach
其实就是一个很简单的遍历
List<Author> authors = dataInit();
authors.stream().forEach(author -> System.out.println(author.getName()));
- count()
这里进行一部分的统计
List<Author> authors = dataInit();
/**这里转换成一个bookList,而后进行计算总共的书籍数目*/
List<Book> bookList = authors.stream().flatMap(author -> author.getBookList().stream())
.collect(Collectors.toList());
long count = authors.stream().flatMap(author -> author.getBookList().stream()).count();
System.out.println(count);
/**NOTE 这里统计了一下每个作者下面的书籍数目,注意这两个的区别*/
List<Integer>bookNum=authors.stream().map(author -> author.getBookList().size()).collect(Collectors.toList());
- max或min
/** 获取书籍的最大值域最小值*/
List<Author> authors = dataInit();
/** 获取书籍的最大值域最小值*/
System.out.println(authors);
List<Book>bookList=authors.stream().flatMap(author -> author.getBookList().stream()).collect(Collectors.toList());
List<Integer> bookNum=authors.stream().map(author -> author.getBookList().size()).collect(Collectors.toList());
System.out.println(bookList);
Optional<Integer> maxValue = authors.stream()
.flatMap(author -> author.getBookList().stream())
.map(book -> book.getWordNum())
.max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
Optional<Integer> minValue = authors.stream()
.flatMap(author -> author.getBookList().stream())
.map(book -> book.getWordNum()).min(((o1, o2) -> o1 - o2));
System.out.println(maxValue.get());
System.out.println(minValue.get());
- collect()
- collect(Collectors.toList())
List<Author> authors = dataInit();
List<String> nameList = authors.stream().map(author -> author.getName()).collect(Collectors.toList());
System.out.println(nameList);
//结果
output--->[alpha, beta, gamma, gamma, delta]
//这里可以看到,这里的结果是有重复值的,但是author 的List 创建是使用new来创建的,所以直接使用authors.stream().distinct().collect(Collectors.toList())并不会去重,因为这里实用的是equals()方法来进行判断,两个object是不可能相等所以这里使用另外一个办法进行去重,TreeSet(),这里就跟[前面文章](https://blog.youkuaiyun.com/muyuchenzi/article/details/128828880?spm=1001.2014.3001.5502)的List去重联系上来了。
List<Author> authors = dataInit();
authors.forEach(System.out::println);
Set<Author> authorsName = new TreeSet<>((Comparator.comparing(Author::getName)));
// authors.forEach(author -> authorsName.add(author.getName()));
authorsName.addAll(authors);
System.out.println("treeSet:"+authorsName);
authorsName.forEach(System.out::println);
- toSet()
这里获取一个author的Name的Set()还有就是通过flatMap来获取BookList的Set。
public static void toSetFunc(){
List<Author> authors = dataInit();
Set<String> authorListNameSet = authors.stream().map(author -> author.getName()).collect(Collectors.toSet());
System.out.println(authorListNameSet);
Set<Book> bookListSet = authors.stream()
.flatMap(author -> author.getBookList().stream())
.collect(Collectors.toSet());
bookListSet.forEach(System.out::println);
}
- toMap()
这里要用到前面的一个对Name的去重办法,因为Map的key是不能重复的,author的List有两个相同的值alpha,所以需要去重,不然报错
public static void collectToMapFunc(){
//这里首先用的是一个key=name,value=score来组成的Map
List<Author> authors = dataInit();
TreeSet<Author> authorTreeSet = new TreeSet<>(Comparator.comparing(Author::getName));
authorTreeSet.addAll(authors);
System.out.println(authorTreeSet.size());
authorTreeSet.forEach(System.out::println);
Map<String, Integer> collectMap = authorTreeSet.stream()
.collect(Collectors.toMap(author -> author.getName(), author -> author.getScore()));
System.out.println(collectMap);
//这里还有一个需求就是name与author的booklist来组成
Map<String, List<Book>> bookListMap = authorTreeSet.stream().collect(Collectors.toMap(new Function<Author, String>() {
@Override
public String apply(Author author) {
return author.getName();
}
}, new Function<Author, List<Book>>() {
@Override
public List<Book> apply(Author author) {
return author.getBookList();
}
}));
for(String key:bookListMap.keySet()){
System.out.println(key+": "+bookListMap.get(key));
}
}
- anyMathc、allMatch、noneMatch
List<Author> authors = dataInit();
boolean nameHasBeta = authors.stream().anyMatch(author -> author.getName().equals("beta"));
boolean biggerThan70 = authors.stream().allMatch(author -> author.getScore() > 70);
boolean noneBiggerThan100 = authors.stream().noneMatch(author -> author.getScore() > 100);
System.out.println(biggerThan70);
System.out.println(nameHasBeta);
System.out.println(noneBiggerThan100);
- findAny
这里是用到了一个optional,这个意思就是一个选项,如果存在的话—>ifPresent(new Consumer)进行
public static void findAny(){
List<Author> authors = dataInit();
Optional<Author> optionalAuthor = authors.stream()
.filter(author -> author.getScore()>70).findAny();
optionalAuthor.ifPresent(new Consumer<Author>() {
@Override
public void accept(Author author) {
System.out.println(author.getName());
}
});
}
- findFirst()
找最小的,或者最大的,其实还有一个办法就是使用前面的max,或者min,然后filter就可以了。
List<Author> authors = dataInit();
List<Author> sortedAuthor2 = authors.stream().sorted(Comparator.comparing(author -> author.getScore())).collect(Collectors.toList());
List<Author> sortedAuthor = authors.stream().sorted(Comparator.comparingInt(Author::getScore)).collect(Collectors.toList());
Optional<Author> first = sortedAuthor.stream().findFirst();
System.out.println(first);
first.ifPresent(author -> System.out.println(author.getName()));
- reduce
reduce一般跟map相结合来进行计算:这里计算所有作者score的总和
private static void reduceAlpha() {
int[] arr = {1, 2, 34, 5, 9};
int reduce = Arrays.stream(arr).reduce(0, ((left, right) -> left + right));
System.out.println(reduce);
// OptionalInt reduceResult = Arrays.stream(arr).reduce(Integer::sum);
// System.out.println(reduceResult.getAsInt());
}
collect进行操作。
private static void reduceAuthorScoreSum() {
List<Author> authors = dataInit();
Integer reduceResult = authors.stream().map(author -> author.getScore())
.reduce(0, (left, right) -> left + right);
System.out.println(reduceResult);
}
/**求最大值*/
Integer result = authors.stream()
.map(author -> author.getScore())
.reduce(Integer.MIN_VALUE, (left, right) -> left > right ? left : right);
System.out.println(result);
/**求最大值*/
Integer result2 = authors.stream()
.map(author -> author.getScore())
.reduce(Integer.MAX_VALUE, (left, right) -> left < right ? left : right);
System.out.println(result2);
- groupingBy()
collect()也可以对结果进行分组
因为authorList里有相同的名字,所以这里通过名字或者id的长度进行分组
public static void groupBy() {
List<Author> authors = dataInit();
authors.forEach(System.out::println);
Map<Integer, List<String>> groupByScore = authors.stream().map(author -> author.getId()).collect(Collectors.groupingBy(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
}));
Map<Integer, List<String>> groupByName = authors.stream().map(author -> author.getName())
.collect(Collectors.groupingBy(s -> s.length()));
System.out.println(groupByName);
System.out.println(groupByScore);
}
- counting
counting 与maxBy
private static void countFunc() {
List<Author> authors = dataInit();
Long tempVal = authors.stream().flatMap(author -> author.getBookList().stream()).collect(Collectors.counting());
Long tempVal2 = authors.stream().collect(Collectors.counting());
Optional<Author> maxBy = authors.stream().collect(Collectors.maxBy(Comparator.comparing(author -> author.getScore())));
System.out.println(tempVal);
System.out.println(tempVal2);
System.out.println(maxBy);
}
Stream调试
idea是支持stream按步骤查看的。
案例数据
- Author的类
package StreamEnd;
import java.util.List;
/**
* @author: l30043039
* @date: 2023/2/12/10:57
* @project: LambdaFunc
*/
public class Author {
private String name;
private String id;
private Integer score;
private List<Book> bookList;
public Author(String name,String id,Integer score,List<Book>bookList){
this.name=name;
this.id=id;
this.score=score;
this.bookList=bookList;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setScore(Integer score) {
this.score = score;
}
public Integer getScore() {
return score;
}
public void setBookList(List<Book> bookList) {
this.bookList = bookList;
}
public List<Book> getBookList() {
return bookList;
}
@Override
public String toString() {
String string = "Authors {" +
"name = " + this.name +
" id = " + this.id +
" score = " + this.score +
" bookList = " + this.bookList +
"}";
return string;
}
}
- Book类
package StreamEnd;
/**
* @author: l30043039
* @date: 2023/2/12/10:58
* @project: LambdaFunc
*/
public class Book {
private String name;
private String intro;
private String category;
private int wordNum;
public Book(String name,String intro,String category,int wordNum){
this.name=name;
this.intro=intro;
this.category=category;
this.wordNum=wordNum;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setCategory(String category) {
this.category = category;
}
public String getCategory() {
return category;
}
public void setIntro(String intro) {
this.intro = intro;
}
public String getIntro() {
return intro;
}
public void setWordNum(int wordNum) {
this.wordNum = wordNum;
}
public int getWordNum() {
return wordNum;
}
@Override
public String toString() {
String string = "book[" +
"name = " + this.name +
" intro = " + this.intro +
" category = " + this.category +
" wordNum = " + this.wordNum +
"]";
return string;
}
}