一. 概述
Java 流是来自源的支持聚合操作的一系列元素。 流不存储元素。 元素是按需计算的。 元素是从数据源(如集合,数组或 I / O 资源)中消耗的。
流聚合操作类似于 SQL 操作。 我们可以对流应用过滤,映射,缩小,匹配,搜索或排序操作。 流允许链接多个流操作。 与使用外部迭代的集合不同,流在内部进行迭代。
- 推荐文章 Java Stream 过滤器
- 推荐文章 Java 8中处理集合的优雅姿势——Stream
二. 示例
2.1 预设测试数据
@Slf4j
public class Test {
@Data
public static class User {
private Integer id;
private Integer age;
private String userName;
private String edu;
}
static private List<User> users = new ArrayList<>();
static {
User u1 = new User();
u1.setId(1001);
u1.setAge(18);
u1.setUserName("小1");
u1.setEdu("001");
User u2 = new User();
u2.setId(1001);
u2.setAge(16);
u2.setUserName("小2");
u2.setEdu("002");
User u3 = new User();
u3.setId(1003);
u3.setAge(19);
u3.setUserName("小3");
u3.setEdu("001");
User u4 = new User();
u4.setId(1004);
u4.setAge(20);
u4.setEdu("003");
users.add(u1);
users.add(u2);
users.add(u3);
users.add(u4);
}
2.2 List转Map
2.2.1 以实体的某个属性为key, 实体为value, 转成一个Map
/**
* 以实体的某个属性为key, 实体为value, 转成一个Map
*/
@Test
public void test1() {
//将List转换为Map
Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User::getId,
Function.identity()));
System.out.println(JSON.toJSONString(userMap));
}
说明: 如果key存在重复, 会报错, 解决方案保留其中一个
/**
* 以实体的某个属性为key, 某个属性为value, 转成一个Map
* 出现重复key问题时: 合并value
*/
@Test
public void test3() {
//将List转换为Map,解决key冲突的问题。
Map<String, User> userMap = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getEdu,
//value的值
Function.identity(),
//合并两个value值:k1是旧值,k2是新值。
(k1, k2) -> {
log.info(JSON.toJSONString(k1));
log.info(JSON.toJSONString(k2));
return k2;
}));
System.out.println(userMap);
}
2.2.2 以实体的某个属性为key, 某个属性为value, 转成一个Map
/**
* 以实体的某个属性为key, 某个属性为value, 转成一个Map
*/
@Test
public void test2() {
//将List转换为Map
Map<Integer, String> userMap = users.stream().collect(Collectors.toMap(User::getId,
User::getEdu));
System.out.println(JSON.toJSONString(userMap));
}
说明: 当value为空时, 会报错, 解决方案: 用list去接受value
/**
* 测试以实体的某个属性为key, 某个属性为value, 转成一个Map
* 出现重复value为null问题时, 用list去接收value
* 出现key重复时, 合并value值
*/
@Test
public void test4() {
//将List转换为Map,解决key冲突的问题。
Map<Integer, List<String>> collect = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getId,
//value的值,是集合的结构
p -> {
//获取value值
List<String> users = new ArrayList<>();
users.add(p.getUserName());
return users;
},
//集合合并
(List<String> k1, List<String> k2) -> {
k1.addAll(k2);
return k1;
}));
System.out.println(collect);
}
2.3 List 进行分组
2.3.1 List分组, key为某个属性, value为实体类
/**
* List分组
*/
@Test
public void test5() {
Map<String, List<User>> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu));
System.out.println(collect);
}
2.3.2 List分组, key为某个属性, value为某个属性
/**
* List分组, value是某个值
*/
@Test
public void test6() {
Map<String, List<String>> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu,
Collectors.mapping(User::getUserName, Collectors.toList())));
System.out.println(collect);
}
2.4 List过滤
/**
* list过滤, 过滤年龄大于18的数据
*/
@Test
public void test7() {
List<User> collect = users.stream().filter(p -> p.getAge() > 18).collect(Collectors.toList());
System.out.println(collect);
}
2.5 计算求和
/**
* 年龄累加
*/
@Test
public void test8() {
Integer reduce = users.stream().map(User::getAge).reduce(0, (o1, o2) -> o1 + o2);
System.out.println(reduce);
}
2.6 查找极值
2.6.1 查找最大值
/**
* 查找最大值
*/
@Test
public void test9() {
Optional<User> collect = users.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge)));
collect.ifPresent(user -> System.out.println(user.getAge()));
}
2.6.2 查找最小值
/**
* 查找最小值值
*/
@Test
public void test10() {
Optional<User> collect = users.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));
collect.ifPresent(user -> System.out.println(user.getAge()));
}
2.7 去重
/**
* 去除id重复的值
*/
@Test
public void test11() {
ArrayList<User> collect = users.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingInt(User::getId))), ArrayList::new
)
);
System.out.println(collect);
}
/**
* putIfAbsent() 方法是
* 如果 key对应的value值不存在, key value 添加到 map 中,并返回 null
* 如果 key对应的value值已存在, key value 不再添加到 map 中, 并返回原 value
*
* 故 newKey(这里的newKey对应user对象中的name的值), 如果(newKey, Boolean.TRUE) 在map中已存在,
* putIfAbsent(newKey, Boolean.TRUE) 会返回 Boolean.TRUE (Boolean.TRUE 被final修饰,故其地址值唯一, 可用作比较)
* 然后判断是否等于 null, 返回false, filter接收到结果为false的Predicate并将该值过滤掉
* @param keyExtractor
* @param <T>
* @return
*/
private static <T> Predicate<T> distinctByVariable(Function<? super T, ?> keyExtractor) {
HashMap<Object, Boolean> map = new HashMap<>();
return t->map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
// 根据id和用户名去重
@Test
public void test12(){
List<User> userList = users.stream().filter(distinctByVariable(u -> {
return u.getUserId() + u.getUsername();
})).collect(Collectors.toList());
userList.forEach(s-> System.out.println(s.getUserId()+"-"+s.getUsername()));
}
2.8 集合元素校验
/**
* 判断tweet 是否包含集合里的某个元素
*/
@Test
public void teat1(){
final List<String> keywords = Arrays.asList("brown", "fox", "dog", "pangram");
final String tweet = "The quick brown fox jumps over a lazy dog. #pangram http://www.rinkworks.com/words/pangrams.shtml";
boolean match = keywords.stream().anyMatch(tweet::contains);
System.out.println(match);
}
网友评论