Stream/Optional常用方法

Stream流

Stream流

1.快速创建list

@Data
@AllArgsConstructor
public class User {
	private String name;
	private String age;
	private int height;
}
// 创建三个user
User user1 = new User("111", "18", 180);
User user2 = new User("222", "18", 175);
User user3 = new User("333", "19", 170);
//添加userList
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
userList.add(user3);

Stream流:创建动态list,可以添加元素

// stream流,创建的是动态数组,可以添加元素
List<User> userList = Stream.of(user1, user2, user3).collect(Collectors.toList());
//如果创建一个固定长度的list,可以使用Arrays.asList(…args)直接返回一个list
// 本质是将一个数组转成list,数组的大小是固定的,所以此list不能添加元素
// 如果调用add方法增加新的元素,会报异常:java.lang.UnsupportedOperationException
List<String> s = Arrays.asList("1","2","3") 

2.遍历

// 遍历
List<String> userNameList = new ArrayList<>();
for (User user : userList) {
	userNameList.add(user.getName());
}
// Stream流
List<String> userNameList = userList.stream().map(User::getName).collect(Collectors.toList());

3.过滤

List<User> newUserList = new ArrayList<>();
// if判断
for (User user : userList) {
	if(user.getName() != null) {
		newUserList.add(user); 
	}
}
//stream流filter
// 获取userName不为空的user的List
List<User> userList = userList.stream().filter(user-> user.getName() != null).collect(Collectors.toList());

4.分组

Map<String, List<User>> map = new HashMap<>();
// if判断
for (User user : userList) {
	if (map.get(user.getAge()) == null) {
		map.put(user.getAge(), new ArrayList());
	}
	map.get(user.getAge()).add(user);
}
//Stream流:groupingBy
Map<String, List<User>> map =userList.stream().collect( Collectors.groupingBy(User::getAge, Collectors.toList()));

5.求和 最值

// int、double、long:
double max = userList.stream().mapToDouble(User::getHeight).sum();
//获取身高最高的人
User maxPeople = userList.stream().max(Comparator.companing(User::getHeight)).get();
//获取身高最低的人
User minPeople = userList.stream().min(Comparator.companing(User::getHeight)).get();

6.List转Map:

第一种(会出现键重复异常):

//以id为主键转为map
Map<Long, User> map = list.stream().collect(Collectors.toMap(User::getId,Function.identity()));


//Function.identity() 是一个函数式接口 Function 中的静态方法,它返回一个可以将输入参数作为输出的身份映射的函数。
//具体来说,Function.identity() 返回一个函数,接受一个参数并将其原样返回。这在需要传递一个函数,但不需要进行任何转换或处理时非常有用。
//这个方法的作用类似于一个传递函数或占位函数,它在某些场景下可以简化代码,并使其更具可读性。例如,在流式操作中,有时需要传递一个函数来映射或转换对象,但又不需要进行任何实际的转换时,可以使用 Function.identity()。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> namesCopy = names.stream()
                              .map(Function.identity())
                              .collect(Collectors.toList());
//在这个例子中,我们在 map() 操作中传递了 Function.identity(),它实际上将每个输入名称映射为相同的输出名称。所以,namesCopy 列表将包含与 names 列表相同的元素。

第二种(针对第一种方法会出现情况):

//给出key重复时,使用哪个key作为主键,以下代码中的(key1, key2) -> key2)代表key1和key2键重复时返回key2做主键
Map<Long, User> map = list.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));

Map<Integer, Pig> mapById = pigs.stream()
        .collect(
                Collectors.toMap(
                        Pig::getId,
                        a -> a,
                        (k1, k2) -> k1)//如果id相同,取第1个
        );
mapById.forEach((k, v) -> {
    System.out.println(k + " -> " + v.toString());
});

//stream():将 List 转换为 Stream。
//collect():将 Stream 中的元素收集到一个结果容器中。
//Collectors.toMap():使用提供的键和值映射函数将 Stream 元素收集到一个 Map 中。
//Pig::getId:用于提取 Pig 对象的 id 作为键。
//a -> a:用于指定将每个 Pig 对象本身作为值。
//(k1, k2) -> k1:用于指定当发现相同的键时,选择保留第一个出现的 Pig 对象作为值。
//最后,通过 mapById.forEach() 循环遍历并打印 Map 中的键值对:
//(k, v) -> { System.out.println(k + " -> " + v.toString()); } 是一个 lambda 表达式,用于迭代并打印 mapById 中的每个键值对。k 代表键,v 代表值。
//这就是 (k, v) 来源的地方。在 mapById.forEach() 方法中,我们使用 lambda 表达式来定义一个函数,该函数接受两个参数 k 和 v,并在每次迭代时被调用。
//在每次迭代中,将键和值传递给 lambda 表达式,并在控制台上打印出键和对应的值的字符串表示。

第三种(只返回对象里某个属性时):

// 不想返回对象,只返回对象里某个属性时 采用这种方式
Map<Long, String> map = list.stream().collect(Collectors.toMap(User::getId, User::getAge, (key1, key2) -> key2));

第四种(以某个属性分组):

Map<Integer, List> map = list.stream().collect(Collectors.groupingBy(User::getId));

//把相同brand对应的数据按照sku分组
Map<String, List<AppealListAllPojo>> skuMap = brandList.stream().collect(Collectors.groupingBy(e -> e.getSku()));

@Test
public void testGroupBy() {
   ArrayList<User> users = new ArrayList<>();
   
   Boolean mulFlag = true;
   Map<String, List<User>> collect = mulFlag ?
           // 多个字段进行分组
           users.stream().collect(Collectors.groupingBy(item -> item.getId() + '-' + item.getName())) :
           // 单字段进行分组
           users.stream().collect(Collectors.groupingBy(User::getName));
}

7.map转list

	List<User> userList = new List<>();
    for (String userName : userMap.keySet()) {
		userList.add(userMap.get(userName));
	}

   List<User> userList = userMap.entrySet().stream().map(e ->e.getValue()).collect(Collectors.toList());

8.做判断

1)、anyMatch():
判断的条件里,任意一个元素成功,返回true;
比如我想判断userlList是否有height > 175的:
	userList.stream().anyMatch(user -> user.getHeight() > 175);       --true2)、allMatch():
allMatch:判断条件里的元素,所有的都是,返回true;
比如上面的userlList,我想判断是否全部height > 175的:
    userList.stream().allMatch(user -> user.getHeight() > 175);       --false3)、noneMatch():
与allMatch相反,判断条件里的元素,所有的都不是,返回true
    userList.stream().noneMatch(user -> user.getHeight() > 175);       --false4)、求取目标和:
    userList.stream().filter(user -> user.getHeight() > 175).count();       --1

栗子

//如果有age等于18和17的就返回有帅的人
public Response doCheck(List userList) {
        Response response = new Response();
        List<String> ageList =
            Arrays.asList("17","18");
        // 校验ageList是否存在
        userList.forEach(user -> {
            Optional.ofNullable(user.getAge()).orElseThrow(() -> new BusinessException("有人没有Age!"));
        });
        // 校验Age状态
        userList.stream()
            .filter(user -> ageList.stream().anyMatch(age -> age.equals(user.getAge())))
            .findFirst()
            .ifPresent(i -> {
                response.setMessage("有帅的人");
            });
        return response;
    }
}

9.合并list

//一维
   List<Integer> list1 = Arrays.asList(1, 2, 3);
   List<Integer> list2 = Arrays.asList(4, 5, 6);
   List<Integer> list3 = Arrays.asList(7, 8, 9);
   List<Integer> mergedList = Stream.of(list1, list2, list3).flatMap(Collection::stream).collect(Collectors.toList());
   System.out.println(mergedList);// [1, 2, 3, 4, 5, 6, 7, 8, 9]

//嵌套
   List<String> list1 = Arrays.asList("张三", "李四", "王二麻子");
   List<String> list2 = Arrays.asList("111", "222", "333");
   // 合并前
   List<List<String>> lists = Arrays.asList(list1, list2);
   System.out.println(lists);
   
   // 合并后
   List<String> mergedList = lists.stream().flatMap(Collection::stream).collect(Collectors.toList());
   System.out.println(mergedList);

合输出结果:在这里插入图片描述在这里插入图片描述

10.分页

Map<String,Object> map = Maps.newHashMap();
List list = new ArrayList();
//list -> 当前页所有数据
map.put("list",list.stream().skip((long) (pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList()));
//count -> 记录总条数
map.put("count",list.size());

11.排序

// 根据名称排序
list.stream().sorted(Comparator.comparing(User::getName)).collect(Collectors.toList());

比较器排序

对象list根据对象的某个字段或多个字段排序的几种方法
1、根据成绩排序
list.sort((x,y)->Float.compare(x.getScore(),y.getScore()));//按照成绩正序排序  从小到大
list.sort((x,y)->Float.compare(y.getScore(),x.getScore()));//按照成绩倒序排序  从大到小

2、根据年龄排序
list.sort(Comparator.comparing(Student::getAge);//正序
list.sort(Comparator.comparing(Student::getAge).reversed());//倒序

3、根据年级排序
list.stream().sorted(Comparator.comparing(Student::getGrade)).collect(Collectors.toList());//正序
list.stream().sorted(Comparator.comparing(Student::getGrade).reversed()).collect(Collectors.toList());//倒序

4、先根据年级升序排序,再根据分数降序排序
list.stream().sorted(Comparator.comparing(Student::getGrade).thenComparing(Comparator.comparing(Student::getScore).reversed())).collect(Collectors.toList());

12.去重 截取 跳过

Stream<String> stream = Stream.of("张三", "张三","张三","李四", "王五", "赵六", "刘七");
//去重
List<String> list = stream().distinct().collect(Collectors.toList());
//截取去重后的前2个元素
list = list.stream().limit(2).collect(Collectors.toList();
//跳过去重后的前2个元素
list = list.stream().skip(2).collect(Collectors.toList());

13.map,foreach和peek区别

map:用于对流中的每个元素进行映射处理,然后再形成新的流;
peek:用于 debug 调试流中间结果,不能形成新的流,但能修改引用类型字段的值;
foreach:用于遍历,会中断流操作;

List<Menu> children = all.stream().filter(...).peek(
    m -> m.setChildList(getChildrens(m, all))
).collect(Collectors.toList());
//把 map 换成 peek 了,因为是引用类型,使用 peek 就没必要 set 之后还要进行 return 了
List<Menu> children = all.stream().filter(...).peek(
    m -> m.setChildList(getChildrens(m, all))
).collect(Collectors.toList());

Optional

场景一

PatientInfo patientInfo = patientInfoDao.getPatientInfoById(consultOrder.getPatientId());
if (patientInfo != null) {
    consultInfoResp.setPatientHead(patientInfo.getHead());
}

// 使用Optional 和函数式编程,一行搞定,而且像说话一样
Optional.ofNullable(patientInfo).ifPresent(p -> consultInfoResp.setPatientHead(p.getHead()));

场景二

public void test1() throws Exception {
    Student student = new Student(null, 3);
    if (student == null || isEmpty(student.getName())) {
        throw new Exception();
    }
    String name = student.getName();
    // 业务省略...

    // 使用Optional改造
    Optional.ofNullable(student).filter(s -> !isEmpty(s.getName())).orElseThrow(() -> new Exception());
}

public static boolean isEmpty(CharSequence str) {
    return str == null || str.length() == 0;
}

场景三

public static String getChampionName(Competition comp) throws IllegalArgumentException {
    if (comp != null) {
        CompResult result = comp.getResult();
        if (result != null) {
            User champion = result.getChampion();
            if (champion != null) {
                return champion.getName();
            }
        }
    }
    throw new IllegalArgumentException("The value of param comp isn't available.");
}


//修改后
public static String getChampionName(Competition comp) throws IllegalArgumentException {
    return Optional.ofNullable(comp)
            .map(Competition::getResult)  // 相当于c -> c.getResult(),下同
            .map(CompResult::getChampion)
            .map(User::getName)
            .orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
}

场景四

int timeout = Optional.ofNullable(redisProperties.getTimeout())
					  .map(x -> Long.valueOf(x.toMillis()).intValue())
					  .orElse(10000);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值