Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象, 是一个来自数据源的元素队列并支持聚合操作(https://upload-images.jianshu.io/upload_images/6348370-f8218715507512e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Stream 可以对集合和数组进行一些简化操作,将集合或数组转化为Stream流,使用Stream流中的方法对集合/数组
中的元素进行操作,解决集合中的一些弊端
和以前的Collection操作不同,Stream操作还有两个基础的特征
- Pipelining:中间操作都会返回流对象本身,这样多个操作可以串联成一个管道,如果流式风格(fluent style),这样做可以对操作进行优化,比如延迟执行(laziness)和短路(short-circuiting)
- 内部迭代:以前对集合遍历都是通过Iterator或者增强for的方式,显示的在集合外部进行迭代,这叫做外部迭代,Stream提供了内部迭代的方式,流可以直接调用遍历方法
- 当使用一个流的时候,通常包括3个步骤:获取一个数据源(source) -> 数据转换 -> 执行操作获取想要的结果,每次转换原有Stream对象,返回一个新的Stream对象,这就允许对其操作可以向链条一样排列,变成一个管道
- Stream两种使用方法:
1.在java.util.Collection 中有一个方法 default Stream
2.java.util.stream接口的静态方法of可以获取数组对应的流
staticStream of (T... values)
List list = new ArrayList();
Stream stream1 = list.stream();
Set set = new HashSet();
Stream stream2 = set.stream();
Map map = new HashMap();
Set keySet= map.keySet();
Stream stream3 = keySet.stream();
Collection collection = map.values();
Stream stream4 = collection.stream();
// 获取键值对的映射关系
// Map.entrySet() 这个方法返回的是一个Set>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value),
// 而Set>表示一个映射项的Set。Map.Entry里有相应的getKey和getValue方法,即JavaBean,让我们能够从一个项中取出Key和Value
Set> entries = map.entrySet();
Stream> stream = entries.stream();
// 数组转换为stream流
Integer[] arr = {1,2,3,4,5};
Stream stream5= Stream.of(arr);
- 案例1 : 对列表/数组中的每个元素都乘以2
package NewFeature.JavaStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public static void main(String[] args) {
int[] list = IntStream.range(1, 10).map(i -> i*2).toArray();
for (int value: list) {
System.out.println(value);
}
// or
List result = IntStream.range(10, 20).map(i -> i*2).boxed().collect(Collectors.toList());
for (int value: result) {
System.out.println(value);
}
}
输出:
2
4
6
8
10
12
14
16
18
- 案例2:筛选重复元素
List list = Arrays.asList(1,2,2,3,4,2,1,5);
list.stream().filter(i -> i%2 == 0).distinct().forEach(System.out::println);
输出:
2
4
- 选出以"张"开头、长度为3的名字
List list = new ArrayList();
list.add("张三丰");
list.add("马可波诺");
list.add("张小龙");
list.add("赵无极");
list.add("青龙");
list.add("乔峰");
List shortList = new ArrayList<>();
for (String name:list) {
if (name.length() == 3 && name.startsWith("张")) {
shortList.add(name);
}
}
System.out.println("张开头并且长度为2的名字=" + shortList.toString())
list.stream().filter(value -> value.startsWith("张"))
.filter(value -> value.length() == 3)
.collect(Collectors.toList()).forEach(System.out::print);
- 案例3:限制元素数量
List list = Arrays.asList(2,5,6,6,8,2,12,63,53,13,76);
list.stream().filter(i -> i>5).
distinct().
limit(3).
// skip(1).
collect(Collectors.toList()).
forEach(System.out::println);
输出:
6
8
12
// 加了skip(1)
8
12
- 案例4: Stream支持map方法,接收一个函数作为参数,这个函数被应用到每个元素上,并将其映射成一个新元素
List list = Arrays.asList("wudy", "macBook", "china hello");
List wordLens = list.stream().map(String::length).collect(Collectors.toList());
for (Integer item:wordLens) {
System.out.println("长度=" + item);
}
输出:
长度=4
长度=7
长度=11
- 案例5:flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流
List list = Arrays.asList("Hello", "World");
list.stream().map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList())
.forEach(System.out::print)
输出:
HeloWrd
如下图:
-案例6:给定两个数字列表,返回所有的数对?例如:给定列表[1,3]、[2,4,6], 应该返回[(1,2),(1,4),(1,6),(3,2),(3,4),(3,6)]
List list1 = Arrays.asList(1,3);
List list2 = Arrays.asList(2,4,6);
List pairs = list1.stream().flatMap(i -> list2.stream()
.map(j -> new int[] {i, j}))
.collect(Collectors.toList());
// pairs.stream().forEach(item -> Arrays.stream(item).forEach();
for (int [] item: pairs) {
System.out.println(Arrays.toString(item));
}
输出:
[1, 2]
[1, 4]
[1, 6]
[3, 2]
[3, 4]
[3, 6]
- 案例7: 匹配给定的谓词
List list = Arrays.asList("wudy","peter");
if (list.stream().anyMatch(value -> value.equals("peter"))) {
System.out.println("匹配到了给定的谓词");
}
输出:
匹配到了给定的谓词
- 案例8: 流中是否所有的元素能匹配给定的谓词
List list = Arrays.asList(5,7,11,423,54);
if (list.stream().allMatch(value -> value > 3)) {
System.out.println("匹配了所有的谓词");
}
输出:
匹配了所有的谓词
- 案例9: 流中没有任何元素能匹配给定的谓词
List list = Arrays.asList(101,198,112,423,354);
if (list.stream().noneMatch(value -> value < 100)) {
System.out.println("都能活到100岁");
}
输出:
都能活到100岁
- 案例10: 求Sum、max
List list = Arrays.asList(1,2,3,4,5,6);
// Integer sum = list.stream().reduce(0, (a, b) -> a + b);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println("sum=" + sum);
Integer max = list.stream().reduce(0, Integer::max);
System.out.println("max=" + max);
输出:
sum=21
max=6
- 案例11:现在有一个List集合,想对该集合中的数据分组处理
package NewFeature.JavaStream;
public class User {
private Integer id;
private Integer age;
private String name;
public User(Integer id, Integer age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public Integer getId() {
return id;
}
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setAge(Integer age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
}
package NewFeature.JavaStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 现在有一个List集合,想对该集合中的数据分组处理
*/
public class StreamDemo {
public static void main(String[] args) {
List list = getUserList();
Map> userGroupList = list.stream().collect(Collectors.groupingBy(User::getAge));
System.out.println(userGroupList);
// for (Integer key: userGroupList.keySet()) {
// System.out.println(userGroupList.get(key));
// }
//
// for (List value: userGroupList.values()) {
// System.out.println(value);
// }
}
public static ArrayList getUserList() {
User user1 = new User(1, 18, "wudy");
User user2 = new User(2, 20, "peter");
User user3 = new User(3, 30, "timo");
User user4 = new User(4, 20, "chimmy");
ArrayList arrayList = new ArrayList();
arrayList.add(user1);
arrayList.add(user2);
arrayList.add(user3);
arrayList.add(user4);
return arrayList;
}
}
输出:
{18=[NewFeature.JavaStream.User@5b6f7412], 20=[NewFeature.JavaStream.User@27973e9b, NewFeature.JavaStream.User@312b1dae], 30=[NewFeature.JavaStream.User@7530d0a]}
- Java8中Stream对列表去重的几种方法
1.distinct() 对于 String 列表的去重
@Test
public void stream1(){
List list = new ArrayList<>();
list.add("A");
list.add("C");
list.add("B");
list.add("C");
System.out.println("去重前=" + list);
list = list.stream().distinct().collect(Collectors.toList());
System.out.println("去重后=" + list);
}
去重前=[A, C, B, C]
去重后=[A, C, B]
2.对实体类列表的去重
// 定义实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "message")
public class Message implements Serializable {
@ApiModelProperty(value = "用户司机企业的id")
private Long uid;
@ApiModelProperty(value = "客服id")
private String agentId;
@ApiModelProperty(value = "客服名称")
private String agentName;
}
// 实现类 MessageServiceImpl
package cn.huolala.llim.im.service.impl;
@Service
public class MessageServiceImpl extends ServiceImpl implements IMessageService {
@Autowired
private IMessageMapper iMessageMapper;
@Override
public List queryList(Message message, PageBO pager) {
// 多条件构造器
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper
.select("uid", "agent_id", "agent_name") // 查询指定字段
.isNotNull("uid").eq("uid", message.getUid());
queryWrapper.orderByDesc("created_at");
Page page = new Page<>(pager.getPage_no(), pager.getPage_size());
page = iMessageMapper.selectPage(page, queryWrapper);
return page.getRecords();
}
}
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
@Test
public void stream() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Message message = new Message();
message.setUid(113074491521L);
PageBO page = new PageBO();
page.setPage_no(1);
page.setPage_size(10);
// 1. 对于 Message 列表去重
List messageList = iMessageService.queryList(message, page);
System.out.println("去重前=" + messageList);
// System.out.println("writeValueAsString = " + objectMapper.writeValueAsString(messageList));
messageList = messageList.stream().distinct().collect(Collectors.toList());
System.out.println("去重后=" + messageList);
// System.out.println("writeValueAsString = " + objectMapper.writeValueAsString(messageList));
messageList = messageList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(Message::getAgentId))), ArrayList::new)
);
System.out.println("根据agentID去重后=" + messageList);
}
<== Columns: uid, agent_id, agent_name
<== Row: 113074491521, 107, wudy.yu2
<== Row: 113074491521, 107, wudy.yu
<== Row: 113074491521, 108, wudy.yu3
<== Row: 113074491521, 107, wudy.yu
去重前=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=107, agentName=wudy.yu), Message(uid=113074491521, agentId=108, agentName=wudy.yu3), Message(uid=113074491521, agentId=107, agentName=wudy.yu)]
去重后=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=107, agentName=wudy.yu), Message(uid=113074491521, agentId=108, agentName=wudy.yu3)]
根据agentID去重后=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=108, agentName=wudy.yu3)]
3.根据List
// 见上例
messageList = messageList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(Message::getAgentId))), ArrayList::new)
);
4.通过 filter() 方法
//我们首先创建一个方法作为 Stream.filter() 的参数,其返回类型为 Predicate,原理就是判断一个元素能否加入到 Set 中去,代码如下:
private static Predicate distinctByKey(Function super T, ?> keyExtractor){
Set
@Test
public void stream() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Message message = new Message();
message.setUid(113074491521L);
PageBO page = new PageBO();
page.setPage_no(1);
page.setPage_size(10);
// 1. 对于 Message 列表去重
List messageList = iMessageService.queryList(message, page);
System.out.println("去重前=" + messageList);
messageList = messageList.stream().distinct().collect(Collectors.toList());
System.out.println("去重后=" + messageList);
//这里我们将 distinctByKey() 方法作为 filter() 的参数,过滤掉那些不能加入到 set 的元素
messageList = messageList.stream().filter(distinctByKey(Message::getAgentId)).collect(Collectors.toList());
System.out.println("根据agentID去重后=" + messageList);
}
<== Columns: uid, agent_id, agent_name
<== Row: 113074491521, 107, wudy.yu2
<== Row: 113074491521, 107, wudy.yu
<== Row: 113074491521, 108, wudy.yu3
<== Row: 113074491521, 107, wudy.yu
<== Total: 4
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1f6af096]
去重前=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=107, agentName=wudy.yu), Message(uid=113074491521, agentId=108, agentName=wudy.yu3), Message(uid=113074491521, agentId=107, agentName=wudy.yu)]
去重后=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=107, agentName=wudy.yu), Message(uid=113074491521, agentId=108, agentName=wudy.yu3)]
根据agentID去重后=[Message(uid=113074491521, agentId=107, agentName=wudy.yu2), Message(uid=113074491521, agentId=108, agentName=wudy.yu3)]
- 案例1
如果有一个需求,需要对数据库查询到的菜肴进行一个处理:
筛选出卡路里小于400的菜肴
对筛选出的菜肴进行一个排序
获取排序后菜肴的名字
public class Dish {
private String name;
private boolean vegetarian;
private int calories;
private Type type;
// getter and setter
}
// java8之前的实现方式
private List beforeJava7(List dishList) {
List lowCaloricDishes = new ArrayList<>();
//1.筛选出卡路里小于400的菜肴
for (Dish dish : dishList) {
if (dish.getCalories() < 400) {
lowCaloricDishes.add(dish);
}
}
//2.对筛选出的菜肴进行排序
Collections.sort(lowCaloricDishes, new Comparator() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getCalories(), o2.getCalories());
}
});
//3.获取排序后菜肴的名字
List lowCaloricDishesName = new ArrayList<>();
for (Dish d : lowCaloricDishes) {
lowCaloricDishesName.add(d.getName());
}
return lowCaloricDishesName;
}
// java8之后的实现方式
private List afterJava8(List dishList) {
return dishList.stream()
.filter(d -> d.getCalories() < 400) //筛选出卡路里小于400的菜肴
.sorted(comparing(Dish::getCalories)) //根据卡路里进行排序
.map(Dish::getName) //提取菜肴名称
.collect(Collectors.toList()); //转换为List
}
高高兴兴写完需求这时候又有新需求了,新需求如下:
对数据库查询到的菜肴根据菜肴种类进行分类,返回一个Map>的结果
这要是放在jdk8之前肯定会头皮发麻
// java8之前的实现方式
private static Map> beforeJdk8(List dishList) {
Map> result = new HashMap<>();
for (Dish dish : dishList) {
//不存在则初始化
if (result.get(dish.getType())==null) {
List dishes = new ArrayList<>();
dishes.add(dish);
result.put(dish.getType(), dishes);
} else {
//存在则追加
result.get(dish.getType()).add(dish);
}
}
return result;
}
// java8的实现方式
private static Map> afterJdk8(List dishList) {
return dishList.stream().collect(groupingBy(Dish::getType));
}
一、什么是流?
流是从支持数据处理操作的源生成的元素序列,源可以是数组、文件、集合、函数。流不是集合元素,它不是数据结构并不保存数据,它的主要目的在于计算
二、如何生成流
生成流的方式主要有五种:
// 2.1>通过集合生成,应用中最常用的一种
List integerList = Arrays.asList(1, 2, 3, 4, 5);
Stream stream = integerList.stream();
// 2.2>通过集合的stream方法生成流
// 2.2.1> 通过数组生成
int[] intArr = new int[]{1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(intArr);
/*
通过Arrays.stream方法生成流,并且该方法生成的流是数值流【即IntStream】而不是Stream。
补充一点使用数值流可以避免计算过程中拆箱装箱,提高性能。Stream API提供了mapToInt、mapToDouble、mapToLong三种方式将对象流
【即Stream】转换成对应的数值流,同时提供了boxed方法将数值流转换为对象流
*/
// 2.2.2> 通过值生成
// 通过Stream的of方法生成流,通过Stream的empty方法可以生成一个空流
Stream stream = Stream.of(1, 2, 3, 4, 5);
// 2.3> 通过文件生成
// 通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行
Stream lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())
//2.4> 通过函数生成
//提供了iterate和generate两个静态方法从函数中生成流
Stream stream = Stream.iterate(0, n -> n + 2).limit(5);
// iterate方法接受两个参数,第一个为初始化值,第二个为进行的函数操作,因为iterator生成的流为无限流,通过limit方法对流进行了截断,只生成5个偶数
Stream stream = Stream.generate(Math::random).limit(5);
//generate方法接受一个参数,方法参数类型为Supplier,
//由它为流提供值。generate生成的流也是无限流,因此通过limit对流进行了截断
- 流的操作类型
流的操作类型主要分为两种:
1.中间操作 一个流可以后面跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的filter、map等
2.终端操作 一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。终端操作的执行,才会真正开始流的遍历。如下面即将介绍的count、collect等
参考资料: https://mp.weixin.qq.com/s?__biz=MzUxOTc4NjEyMw==&mid=2247506967&idx=2&sn=c9c4b190331dc53faf77f8185e9fd534&chksm=f9f6c7f3ce814ee59109d3f2496eae5feaa46ef09fbc098e2c0d02be591fdeb043a3389c0cbc&mpshare=1&scene=23&srcid=0427RZolHIHFZHAY2n3NoRkE&sharer_sharetime=1619505638932&sharer_shareid=f770d25bc57f1c2f9159f85750f854dc#rd
- Stream对列表去重的几种方法
- 1.Stream的distinct方法
distinct()
是Java 8 中Stream
提供的方法,返回的是由该流中不同元素组成的流。distinct()使用hashCode()
和eqauls()
方法来获取不同的元素。
因此,需要去重的类必须实现hashCode()
和equals()
方法。换句话讲,我们可以通过重写定制的hashCode()
和equals()
方法来达到某些特殊需求的去重。
distinct()
方法声明如下:- 1.1 对String列表去重:
因为 String 类已经覆写了 equals() 和 hashCode() 方法,所以可以去重成功
@Test
public void distinct(){
List stringList = new ArrayList(){
{
add("A");
add("B");
add("C");
add("A");
}
};
System.out.println("去重前:");
for (String s : stringList){
System.out.println(s);
}
stringList = stringList.stream().distinct().collect(Collectors.toList());
System.out.println("去重后:");
for (String s : stringList){
System.out.println(s);
}
}
去重前:
A
B
C
A
去重后:
A
B
C
- 1.2 对实体类列表的去重
注:代码中我们使用了Lombok
插件的@Data
注解,可自动覆写equals()
以及hashCode()
方法
@Test
public void distinct() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List sList = new ArrayList<>();
Student s1 = Student.builder().stuNo("001").name("wudy").build();
Student s2 = Student.builder().stuNo("002").name("peter").build();
Student s3 = Student.builder().stuNo("001").name("wudy").build();
sList.add(s1);
sList.add(s2);
sList.add(s3);
System.out.printf("去重前:" + mapper.writeValueAsString(sList));
sList = sList.stream().distinct().collect(Collectors.toList());
System.out.printf("去重后:" + mapper.writeValueAsString(sList));
}
去重前:[{"stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"},{"stuNo":"001","name":"Tom"}]
去重后:[{"stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"}]
- 1.3 根据List
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
@Test
public void test21() throws JsonProcessingException {
List list = new ArrayList<>();
Student s1 = Student.builder().stuNo("001").stuName("wudy").build();
Student s2 = Student.builder().stuNo("002").stuName("peter").build();
Student s3 = Student.builder().stuNo("001").stuName("wudy").build();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectMapper mapper = new ObjectMapper();
System.out.printf("去重前=" + mapper.writeValueAsString(list));
list = list.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getStuName))), ArrayList::new)
);
System.out.printf("去重后=" + mapper.writeValueAsString(list));
}
去重前=[{"stuName":"wudy","stuNo":"001"},{"stuName":"peter","stuNo":"002"},{"stuName":"wudy","stuNo":"001"}]
去重后=[{"stuName":"peter","stuNo":"002"},{"stuName":"wudy","stuNo":"001"}]
- 1.4 通过filter方法去重
@Test
public void test21() throws JsonProcessingException {
List list = new ArrayList<>();
Student s1 = Student.builder().stuNo("001").stuName("wudy").build();
Student s2 = Student.builder().stuNo("002").stuName("peter").build();
Student s3 = Student.builder().stuNo("001").stuName("wudy").build();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectMapper mapper = new ObjectMapper();
System.out.printf("去重前=" + mapper.writeValueAsString(list));
// 将 distinctByKey() 方法作为 filter() 的参数,过滤掉那些不能加入到 set 的元素
list = list.stream().filter(dictinctByKey(Student::getStuName)).collect(Collectors.toList());
System.out.printf("去重后=" + mapper.writeValueAsString(list));
}
private static Predicate dictinctByKey(Function super T, ?> keyExtractor){
Set
去重前=[{"stuName":"wudy","stuNo":"001"},{"stuName":"peter","stuNo":"002"},{"stuName":"wudy","stuNo":"001"}]
去重后=[{"stuName":"wudy","stuNo":"001"},{"stuName":"peter","stuNo":"002"}]
Stream图解
Stream
将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等
Stream可以由数组或集合创建,对流的操作分为两种:
中间操作,每次返回一个新的流,可以有多个。
终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。
另外,Stream有几个特性:
- stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
- stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
- stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
- 1.Stream创建:
1.1> Stream可以通过集合数组创建,通过 java.util.Collection.stream() 方法用集合创建流
List list = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream stream = list.stream();
// 创建一个并行流
Stream parallelStream = list.parallelStream();
1.2> 使用java.util.Arrays.stream(T[] array)方法用数组创建流
int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);
1.3> 使用Stream的静态方法:of()、iterate()、generate()
Stream stream = Stream.of(1, 2, 3, 4, 5, 6);
Stream stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
Stream stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);
stream
和parallelStream
的简单区分: stream
是顺序流
,由主线程按顺序对流执行操作,而parallelStream
是并行流
,内部以多线程
并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数,两者的处理不同之处
Stream的案例使用
https://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247539728&idx=2&sn=a3397ae7db0d7c13f21ae4d650b237ec&chksm=eb50d926dc275030a3ac919708b53af1a4bd339bce6e4f1351fd1eb88f9a5c2fdecdd2c6b02b&mpshare=1&scene=23&srcid=08216nSfljTSZcpp5Nql4z7m&sharer_sharetime=1629510377638&sharer_shareid=f770d25bc57f1c2f9159f85750f854dc%23rd
Stream简单案例
https://mp.weixin.qq.com/s?__biz=MzUxOTc4NjEyMw==&mid=2247533024&idx=3&sn=393d7130c992ab67d5ce2dde66b165dc&chksm=f9f65a04ce81d312c3edc482d796f68b250e9bca943c77ce10e36e16e6a3c0850f10d58a7c24&mpshare=1&scene=23&srcid=0521nfdgr7cnkMhqRtFFGqz2&sharer_sharetime=1653147530521&sharer_shareid=7fec9c1809ccb850bfdebba7d4f7a81e%23rd
// 1.list => 数组
List arrayList = new ArrayList(Arrays.asList(1,3,5,7,9));
// int[] arr = arrayList.stream().mapToInt((item) -> Integer.valueOf(item)).toArray();
int[] arr = arrayList.stream().mapToInt(Integer::intValue).toArray();
for (int i=0;i list
int[] arr2 = {2,4,6,8};
List list = Arrays.stream(arr2).boxed().collect(Collectors.toList());
for (Integer item: list) {
System.out.println("item="+ item);
}
// 3.统计数组中的元素
String[] arr3 = {"a", "c", "a", "b", "d", "c"};
// 第一个参数代表将arr中的每一个元素作为Map中的key,第二个参数代表每一个key所对应的value,在这里每一个元素都对应个数1,第三个参数代表,如果存在相同的key,该如何进行合并,这里通过使用Integer::sum,代表将具有相同key的元素进行合并时,其value进行相加
Stream.of(arr3).collect(Collectors.toMap(k -> k, k -> 1, Integer::sum))
.forEach((k, v) -> System.out.println(k + ": " + v));
// 4.基本数据类型的数组自定义排序
int[] arr4 = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
int[] arr5 = IntStream.of(arr4).boxed()
.sorted(Comparator.reverseOrder())
.mapToInt(Integer::intValue)
.toArray();
for (Integer item:arr5) {
System.out.println("item5="+ item);
}
// 5.统计数组中前 k 个个高频元素
int[] arr6 = {1,3,2,55,33,3,6,1,55,3,2,0,98,3,1,41,52,2,1,3};
int[] arr7 = Arrays.stream(arr6)
.boxed()
.collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
.entrySet()
.stream()
.sorted((m1, m2) -> m2.getValue() - m1.getValue())
.limit(2)
.mapToInt(Map.Entry::getKey)
.toArray();
for (Integer item:arr7) {
System.out.println("item7="+ item);
}