首页 > 其他分享 >自从用了 Stream,代码更简洁优雅了!

自从用了 Stream,代码更简洁优雅了!

时间:2023-03-07 15:55:55浏览次数:51  
标签:arr 简洁 Stream stream int 代码 list 优雅 数组

来源:blog.csdn.net/qq_41698074/article/details/108502976

前言

虽然 stream在 Java8 中就已经被引入,但是大多数人却没有去使用这个十分有用的特性,本文就通过介绍几个通过使用stream让代码更简洁、可读,来让你了解stream的方便之处。

技巧

数组转集合

相信经常刷LeetCode的小伙伴,偶尔会遇到需要将List与基本类型数组进行互转的情况,然后就需要写像下面这样的代码:

// 将 List 元素存储到数组中
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
int[] arr = new int[list.size()];
Integer[] temp = list.toArray(new Integer[0]);
for (int i = 0; i < temp.length; i++) {
 arr[i] = temp[i];
}

// 将数组元素 存储到 List 中
int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = new ArrayList<>();
for (int val : arr) {
 list.add(val);
}

以上两个转换虽然写着还不算麻烦,但是每次都需要写一个循环,尤其在数组转List的时候还需要使用一个临时数组,都会让人看着很不舒服,但是如果使用了stream就会大不一样,用stream实现了相同功能的代码如下:

// 将 List 元素存储到数组中
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();

// 将数组元素 存储到 List 中
int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = IntStream.of(arr).boxed().collect(Collectors.toList());

可以发现通过使用stream,我们能够在写代码的时候更加连贯,代码也更加可靠易维护,注意力也可以放在业务功能上,相信各位就算对lambda语法并不是太熟悉,在阅读上面代码的时候,也很容易能够看懂。

统计数组元素中的个数

假设我们现在需要统计并输出一个有重复元素的数组中每个元素及对应元素出现的个数,相信各位都能够想到,我们使用一个Map就很容易解决这个问题,代码如下:

String[] arr = {"a", "c", "a", "b", "d", "c"};
Map<String, Integer> map = new HashMap<>();
for (String s : arr) {
    if (map.containsKey(s)) {
        map.put(s, map.get(s) + 1);
    } else {
        map.put(s, 1);
    }
}
map.forEach((key, value) -> System.out.println(key + " : " + value));

如果对Map中的API更加熟悉的小伙伴,可能会写出下面这个更加简洁的代码:

String[] arr = {"a", "c", "a", "b", "d", "c"};
Map<String, Integer> map = new HashMap<>();
for (String s : arr) {
    map.put(s, map.getOrDefault(s, 0) + 1);
}
map.forEach((key, value) -> System.out.println(key + " : " + value));

但是,如果使用stream,我们还能写出更加简洁的代码,同样不需要写烦人的循环了,而且只需两行代码即可(为了提高可读性,进行了换行):

String[] arr = {"a", "c", "a", "b", "d", "c"};
Stream.of(arr)
      .collect(Collectors.toMap(k -> k, k -> 1, Integer::sum))
      .forEach((k, v) -> System.out.println(k + " : " + v));
注意

在上面的代码中,Collectors.toMap(k -> k, k -> 1, Integer::sum)这一部分可能不好理解,对于这里面的三个参数,第一个参数代表将arr中的每一个元素作为Map中的key,第二个参数代表每一个key所对应的value,在这里每一个元素都对应个数1,第三个参数代表,如果存在相同的key,该如何进行合并,这里通过使用Integer::sum,代表将具有相同key的元素进行合并时,其value进行相加,这样便实现了每个元素个数的统计。

基本数据类型的数组自定义排序

有时我们会遇到对基本数据类型的数组进行自定义排序的情况,不同于包装类型的数组和集合可以直接使用比较器,我们只能通过将基本数组类型的数组转为包装类型或者存储在集合中,在排序完成后再转为基本类型的数组,再者,我们只能通过手写排序算法,修改排序算法中的比较进行实现。

不管是哪种方法,我们都没办法将精力放在逻辑功能上,必须写一些额外的代码,甚至是修改底层逻辑,就像下面的代码一样(实现数组逆序):

int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
// 将数组转为包装类型再进行自定义排序
Integer[] temp = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
    temp[i] = arr[i];
}
Arrays.sort(temp, Comparator.reverseOrder());
for (int i = 0; i < temp.length; i++) {
    arr[i] = temp[i];
}

// 将数组转为集合类型再进行自定义排序
List<Integer> list = new ArrayList<>();
for (int val : arr) {
    list.add(val);
}
list.sort(Collections.reverseOrder());
for (int i = 0; i < list.size(); i++) {
    arr[i] = list.get(i);
}

// 通过手写排序算法修改比较规则实现
// 为了让代码更加简洁,使用了最暴力且没有优化的冒泡排序
int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr.length - i - 1; j++) {
        if (arr[j] < arr[j + 1]) {
            int temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}

可以发现以上几种方法,我们都需要写很多代码,无法将注意力集中在设计自定义排序这个问题上,但是通过使用stream,我们就可以写出下面这样简洁的代码(如果愿意的话,你也可以把一系列的链式操作写在一行上,但为了代码的可读性,不建议那么做):

int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
arr = IntStream.of(arr)
               .boxed()
               .sorted(Comparator.reverseOrder())
               .mapToInt(Integer::intValue)
               .toArray();
注意

在这里其实为了实现数组的逆序,我们只需要调用Arrays的sort方法,然后再进行数组元素的反转即可,不过因为是为了讲解自定义排序,大多数情况下不会是数组逆序这么简单,所以我就写了更加通用一些的代码。

统计数组中前 k 个个高频元素

在最后,我们通过一道题来进行实战以便更好的体验stream的强大之处,当然我们在练习该题的时候,更需要从算法的角度去考虑该题的解法,不过在本文,我们主要为了讲解stream的使用,所以就不去考虑算法的东西了,而如果使用stream,我们就可以写出下面这样简单易懂的代码:

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        return Arrays.stream(nums)
                     .boxed()
                     .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                     .entrySet()
                     .stream()
                     .sorted((m1, m2) -> m2.getValue() - m1.getValue())
                     .limit(k)
                     .mapToInt(Map.Entry::getKey)
                     .toArray();
    }
}

总结

本文介绍了几个简单、实用的stream使用技巧,当然stream的应用远不止此,希望通过本文,能够激发起你学习stream的兴趣,本文若有错误之处,也欢迎你的指正。

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

标签:arr,简洁,Stream,stream,int,代码,list,优雅,数组
From: https://www.cnblogs.com/javastack/p/17188353.html

相关文章

  • 函数编程:强大的 Stream API
    函数编程:强大的StreamAPI每博一文案只要有人的地方,世界就不会是冰冷的,我们可以平凡,但绝对不可以平庸。——————《......
  • 彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉
    背景在现在流行的系统设计中,一般会将对象模型划分为多个层次,例如VO、DTO、PO、BO等等。这同时也产生了一个问题,经常需要进行不同层级的模型之间相互转换。针对这种问题......
  • 魔音,mp3音乐下载器兼播放器,界面简洁,歌曲资源超多,实现听歌自由!
    前几天有小伙伴反映之前分享的音乐下载器已经不能下载音乐了,提示需要更新,今天给大家带来另一款音乐下载软件,界面简洁、功能更加稳定。一、软件简介魔音(Morin)音乐是一款界......
  • java8新特性-Stream基础
    Stream是跟随Lambda表达式一起发布的java8新特性。是支持串行和并行处理数据的工具。有四种类型的Stream。在StreamShape枚举中定义了Stream的类型。分别是REFERENCE(引用流......
  • 提前中止Java Stream forEach的优雅解决方案
    1.概述JavaStreamforeach是一种声明式的,整洁的遍历循环。但是当我们满足某个条件想要中止这个循环的时候,通常却十分繁琐,比如使用异常,但通常这不是一种很好的实现方案......
  • Wire:Go最优雅的依赖注入工具
    阅读用时:4分钟导语“成熟的工具,要学会自己写代码”。本文介绍了Go依赖注入工具[[Wire]]及其使用方法,以及在实践中积累的各种运用技巧。当代码达到一定规模后,[[Wire]......
  • 如何让错误处理更加优雅
    1.go采用c的err方法,但是容易产生大量的外部判断。packagekillerimport"fmt"typeBookstruct{NamestringPriceintStoreintMember......
  • python+playwright 学习-21.文件上传-优雅处理
    前言如果你之前用过selenium,肯定遇到过文件上传头疼的事,有些控件是input输入框,可以直接传本地文件地址,然而有些需要弹出本地文件选择器的时候就不好处理了。playwright......
  • python+playwright 学习-19.监听dialog事件-优雅处理对话框
    前言网页上的alert弹出框你不知道什么时候弹出来,selenium处理alert弹出框的方式是先判断有没alert再处理,并且只能处理这一次。playwright框架可以监听dialog事件,不管......
  • text/event-stream
    content-type为text/event-streamwebpack热更新需要向浏览器推送信息,一般都会想到websocket,但是还有一种方式,叫做Server-SentEvents(简称SSE)。SSE是websocket的一种轻型......