正确使用stream api

今天给大家分享一下java里的stream api应该如何正确的使用才能真正让我们的代码变得很优雅,因为java推出stream api以后,很多小伙伴觉得特别帅酷炸裂,然后就会在代码里过渡的滥用stream api,最终反而会导致代码变得越来越丑,越来越不清晰,不好维护。

所以大家一定要注意一下stream api的使用,避免滥用,要合理的运用,才能让我们写出一手漂亮的代码来!

在Java的世界里,Stream API无疑是一个让人眼前一亮的特性。它以一种全新的、声明式的方式处理数据集合,使得代码变得更加简洁和易读。然而,有时候开发者会发现,用了Stream之后,代码反而变得不那么美观,甚至有点“丑”。这究竟是怎么回事呢?本文就来探讨一下这个问题。

Java里的Stream是什么?

Stream API是Java 8中引入的一项新特性,它允许你以声明式的方式处理数据集合(包括数组、列表等)。你可以将Stream看作是一种高级迭代器,它提供了一系列的操作,比如筛选、排序、映射等,这些操作可以以一种链式调用的方式组合在一起,从而完成复杂的数据处理任务。

Stream API 的核心概念

  • 数据源 (Source): Stream 的数据来源,比如 Collection、数组或其他提供数据的类。
  • 中间操作 (Intermediate Operations): 这些操作会创建一个新的 Stream,原 Stream 不变。中间操作通常是惰性的,即它们不会立即执行,直到遇到终止操作才会执行。
  • 终止操作 (Terminal Operations): 这些操作会从 Stream 生成结果,执行完后 Stream 就结束了。

Stream API 的使用步骤

  1. 创建 Stream
  2. 执行中间操作
  3. 执行终止操作

中间操作

  • filter: 过滤数据。
  • map: 映射数据。
  • flatMap: 扁平化数据。
  • distinct: 去除重复元素。
  • sorted: 排序数据。
  • peek: 打印或调试数据。

终止操作

  • forEach: 遍历数据。
  • reduce: 归约数据。
  • collect: 收集数据到集合。
  • min: 获取最小值。
  • max: 获取最大值。
  • count: 计算元素数量。
  • anyMatch: 是否存在匹配项。
  • allMatch: 所有元素是否都匹配。
  • noneMatch: 是否没有任何元素匹配。
  • findFirst: 获取第一个元素。
  • findAny: 获取任意一个元素。

Stream的用法示例

下面是一些使用Stream API的示例,通过这些示例,你可以对Stream的用法有一个基本的了解。

示例1:筛选操作

假设你有一个用户列表,需要筛选出年龄大于18岁的用户。

List<User> users = Arrays.asList(  
   new User("Alice", 20),  
   new User("Bob", 17),  
   new User("Charlie", 22)  
);  
 
List<User> adults = users.stream()  
  .filter(user -> user.getAge() > 18)  
  .collect(Collectors.toList());

在这个示例中,filter方法用于筛选年龄大于18岁的用户,collect方法用于将筛选结果收集到一个新的列表中。

示例2:排序操作

假设你需要将用户列表按照年龄进行排序。

List<User> sortedUsers = users.stream()  
  .sorted(Comparator.comparingInt(User::getAge))  
  .collect(Collectors.toList());

在这个示例中,sorted方法用于对用户列表进行排序,排序的依据是用户的年龄。

示例3:映射操作

假设你需要从用户列表中提取出所有用户的姓名。

List<String> names = users.stream()  
  .map(User::getName)  
  .collect(Collectors.toList());

map方法用于提取用户的姓名,并将提取结果收集到一个新的列表中。

为什么用了Stream以后,代码反而越写越丑?

虽然Stream API提供了很多便利的操作,但是如果使用不当,就会导致代码变得难以阅读和维护。下面是一些可能导致代码变“丑”的原因:

1、过度使用:有些开发者为了追求代码的“函数式”,不管三七二十一,什么地方都用Stream,结果导致代码变得难以阅读。比如,一个简单的for循环就能解决的问题,偏偏要用Stream来实现,结果代码行数翻倍,可读性大大降低。

2、链式调用过长:Stream API支持链式调用,这是一个非常强大的特性。但是,如果链式调用过长,就会导致一行代码变得非常长,甚至超过屏幕的宽度,这显然是不利于阅读的。

3、滥用Lambda表达式:Lambda表达式是Stream API的常用搭档,它让代码变得更加简洁。但是,如果滥用Lambda表达式,比如在一个Lambda表达式中嵌套另一个Lambda表达式,就会导致代码变得难以理解和维护。

4、忽视代码的可读性:有些开发者在使用Stream时,过分追求代码的简洁性,而忽视了代码的可读性。他们可能会把多个操作合并到一行代码中,或者使用一些不太常见的Stream操作,导致其他开发者难以理解代码的含义。

下面是一个代码变“丑”的示例:

List<String> result = users.stream()  
  .filter(user -> user.getAge() > 18)  
  .map(user -> {  
       String name = user.getName();  
       return name.toUpperCase();  
  })  
  .sorted((name1, name2) -> name1.compareTo(name2))  
  .collect(Collectors.toList());

虽然使用了Stream API完成了任务,但是代码的可读性并不好。链式调用过长,且Lambda表达式中嵌套了另一个Lambda表达式,这使得代码难以理解和维护。

如何合理用Stream才能让代码保持优雅?

要避免代码变“丑”,我们需要合理使用Stream API。下面是一些建议:

1、不要过度使用:不是所有的地方都适合使用Stream,比如简单的遍历和修改集合元素的操作,使用传统的for循环或者for-each循环可能更加直观和简洁。因此,在使用Stream之前,先思考一下是否真的需要它。

2、控制链式调用的长度:虽然Stream支持链式调用,但是并不意味着你可以无限制地链式下去。当链式调用过长时,可以考虑将其拆分成多个步骤,每个步骤都使用一行代码来表示,这样可以提高代码的可读性。

3、慎用Lambda表达式:Lambda表达式确实可以让代码变得更加简洁,但是并不是所有的情况都适合使用它。比如,当一个Lambda表达式过于复杂时,可以考虑将其拆分成一个独立的方法,这样既可以保持代码的简洁性,又可以提高代码的可读性。

4、注重代码的可读性:在使用Stream时,一定要注重代码的可读性。不要为了追求代码的简洁性而牺牲可读性。比如,可以使用一些有意义的变量名来替代复杂的Lambda表达式,或者使用注释来解释一些不太直观的操作。

下面是一个合理使用Stream的示例:

// 先筛选年龄大于18岁的用户  
List<User> adults = users.stream()  
  .filter(user -> user.getAge() > 18)  
  .collect(Collectors.toList());  
 
// 再提取用户的姓名,并转换为大写  
List<String> names = adults.stream()  
  .map(User::getName)  
  .map(String::toUpperCase)  
  .collect(Collectors.toList());  
 
// 最后对姓名进行排序  
List<String> sortedNames = names.stream()  
  .sorted()  
  .collect(Collectors.toList());

在这个示例中,我们将任务拆分成了多个步骤,每个步骤都使用了一行代码来表示。这样,代码的可读性就大大提高了。同时,我们也避免了过度使用Stream和滥用Lambda表达式的问题。

结语

总的来说,Stream API是一个非常强大的特性,它可以让代码变得更加简洁和易读。但是,如果使用不当,就会导致代码变得“丑”。因此,在使用Stream时,我们需要保持一定的克制和审慎,确保代码的可读性和可维护性。只有这样,我们才能充分利用Stream API的优势,写出更加优雅和高效的代码。

Flink可以使用JDBC连接器来连接TiDB,以下是使用Stream API方式连接TiDB的步骤: 1. 添加TiDB JDBC驱动 在Flink项目的pom.xml文件中添加TiDB JDBC驱动依赖: ```xml <dependency> <groupId>com.pingcap.tidb</groupId> <artifactId>tidb-jdbc</artifactId> <version>${tidb-jdbc-version}</version> </dependency> ``` 2. 创建TiDB连接 使用TiDB JDBC驱动创建TiDB连接,例如: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class TiDBConnection { private static final String JDBC_DRIVER = "com.pingcap.tidb.TiDBDriver"; private static final String DB_URL = "jdbc:tidb://localhost:4000/testdb"; private static final String USER = "root"; private static final String PASS = ""; public static Connection getConnection() throws SQLException { Properties properties = new Properties(); properties.setProperty("user", USER); properties.setProperty("password", PASS); return DriverManager.getConnection(DB_URL, properties); } } ``` 3. 创建Flink流处理程序 使用Flink流处理API创建处理程序,例如: ```java import org.apache.flink.api.common.functions.MapFunction; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TiDBStreamExample { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); DataStream<String> source = env.fromElements("1", "2", "3"); DataStream<String> result = source.map(new MapFunction<String, String>() { @Override public String map(String value) throws Exception { try (Connection conn = TiDBConnection.getConnection(); Statement stmt = conn.createStatement()) { stmt.execute("INSERT INTO test_table (col1) VALUES ('" + value + "')"); } catch (SQLException e) { e.printStackTrace(); } return value; } }); result.print(); env.execute("TiDB Stream Example"); } } ``` 4. 运行程序 运行程序并观察TiDB中的数据是否被正确写入。 需要注意的是,使用TiDB时需要注意分布式事务的问题,可以使用Flink的事务支持来保证数据一致性。另外,TiDB JDBC驱动的版本需要与TiDB的版本匹配,否则可能会出现不兼容的问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值