今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在上期文章中,我们讨论了如何在 Java 中遍历树形结构,包括深度优先搜索 (DFS) 和广度优先搜索 (BFS) 的实现。这些遍历方式在数据结构中起着关键作用,帮助我们理解和处理复杂的层级数据。延续上期内容,树形结构中通常会涉及多个节点及其子节点的信息,而这些数据往往存储在多个对象的 List 中。在实际开发中,我们常常遇到需要将多个对象的 List 数据进行合并的场景,比如合并多个用户列表、商品列表等。
在本文中,我们将重点讲解 Java 怎么把多个对象的 List 数据合并,并探讨合并过程中的不同实现方式、优缺点,以及实际应用场景。
摘要
本文主要讨论如何在 Java 中高效合并多个对象的 List 数据。首先,我们会简要介绍 List 在 Java 中的使用,然后解析不同的 List 合并方法,并展示相应的代码实现。随后,通过具体案例展示合并操作的实际应用场景,最后对各方法的优缺点进行分析,并提供核心方法和测试用例帮助读者理解。
概述
List 的基本概念
List
是 Java 集合框架中的重要接口,继承自 Collection
,表示有序的元素集合,允许存储重复元素。Java 中常用的 List 实现类有:
ArrayList
:基于动态数组实现,查询速度快,但在添加和删除大量数据时性能较差。LinkedList
:基于链表实现,插入和删除操作高效,查询速度相对较慢。
在日常开发中,List
常用于存储一组对象的数据,比如用户对象的列表、订单对象的列表等。
合并多个 List 数据的场景
在实际开发中,常常需要将多个对象的 List 数据进行合并,例如:
- 合并来自不同数据源的用户列表;
- 将多个文件中的商品列表合并为一个完整的商品清单;
- 合并来自多个 API 的订单数据。
通过合并 List,我们可以将分散的数据整合到一个统一的数据结构中,方便后续操作和处理。
源码解析
1. 使用 addAll()
方法合并 List
最直接的方法是使用 addAll()
方法,将一个 List 的所有元素添加到另一个 List 中。
示例代码:
java
import java.util.ArrayList;
import java.util.List;
public class ListMergeExample {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("Apple");
list1.add("Banana");
List<String> list2 = new ArrayList<>();
list2.add("Orange");
list2.add("Grapes");
// 使用 addAll() 合并两个 List
list1.addAll(list2);
// 输出合并后的 List
System.out.println("Merged List: " + list1);
}
}
运行结果:
Merged List: [Apple, Banana, Orange, Grapes]
分析 :addAll()
方法会将第二个 List 中的所有元素添加到第一个 List 中,保留元素的顺序。该方法效率较高,适合用于两个或多个列表的合并。
2. 使用 Stream
API 合并 List
Java 8 引入了 Stream
API,使得合并 List 的操作更加简洁和易于扩展。通过 Stream.concat()
方法,我们可以轻松合并多个 List。
示例代码:
java
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ListMergeWithStream {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("Car");
list1.add("Bike");
List<String> list2 = new ArrayList<>();
list2.add("Bus");
list2.add("Train");
// 使用 Stream API 合并两个 List
List<String> mergedList = Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList());
// 输出合并后的 List
System.out.println("Merged List using Stream: " + mergedList);
}
}
运行结果:
Merged List using Stream: [Car, Bike, Bus, Train]
分析 :Stream.concat()
方法将两个流连接起来,再通过 collect(Collectors.toList())
将流转换回 List
。这种方法可以很方便地扩展为合并多个列表,且代码更加简洁。
3. 使用 Collections.addAll()
方法
Collections.addAll()
是另一个简单合并 List 的方法。它允许我们将数组或多个元素快速添加到 List 中。
示例代码:
java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListMergeWithCollections {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("Dog");
list1.add("Cat");
List<String> list2 = new ArrayList<>();
list2.add("Rabbit");
list2.add("Hamster");
// 使用 Collections.addAll() 方法合并
Collections.addAll(list1, list2.toArray(new String[0]));
// 输出合并后的 List
System.out.println("Merged List using Collections: " + list1);
}
}
运行结果:
Merged List using Collections: [Dog, Cat, Rabbit, Hamster]
分析 :Collections.addAll()
方法是对 addAll()
的进一步封装,它可以将一个数组或列表中的所有元素添加到另一个列表中。这种方式代码简洁,但相对不如 Stream
灵活。
4. 自定义合并逻辑
有时,我们可能需要根据特定的业务逻辑合并 List,比如去重、合并时保留某些属性等。此时可以使用自定义逻辑进行合并。
示例代码:
java
import java.util.ArrayList;
import java.util.List;
class User {
String name;
int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public class CustomListMergeExample {
public static void main(String[] args) {
List<User> list1 = new ArrayList<>();
list1.add(new User("Alice", 30));
list1.add(new User("Bob", 25));
List<User> list2 = new ArrayList<>();
list2.add(new User("Charlie", 22));
list2.add(new User("Alice", 30)); // 重复对象
List<User> mergedList = new ArrayList<>(list1);
// 自定义合并逻辑:避免重复添加
for (User user : list2) {
if (!mergedList.contains(user)) {
mergedList.add(user);
}
}
// 输出合并后的 List
System.out.println("Merged List with custom logic: " + mergedList);
}
}
运行结果:
Merged List with custom logic: [User{name='Alice', age=30}, User{name='Bob', age=25}, User{name='Charlie', age=22}]
分析:自定义逻辑通过遍历第二个 List,并检查目标 List 中是否已存在该对象,防止重复添加。这种方式适用于需要根据具体业务规则合并 List 的场景。
使用案例分享
案例 1:合并不同数据源的订单列表
在电商平台中,订单可能来自不同的数据源,比如第三方支付平台、物流系统等。我们可以通过合并这些不同来源的订单列表,统一处理订单数据。
java
List<Order> orderListFromPayment = fetchOrdersFromPaymentSystem();
List<Order> orderListFromLogistics = fetchOrdersFromLogisticsSystem();
// 使用 Stream API 合并订单列表
List<Order> mergedOrders = Stream.concat(orderListFromPayment.stream(), orderListFromLogistics.stream())
.collect(Collectors.toList());
案例 2:合并多个用户列表并去重
在企业管理系统中,不同部门可能维护独立的用户列表。为了统一管理,我们需要将各部门的用户列表合并,并去除重复用户。
java
List<User> hrUserList = fetchUsersFromHR();
List<User> itUserList = fetchUsersFromIT();
// 使用自定义逻辑合并用户列表并去重
List<User> mergedUsers = new ArrayList<>(hrUserList);
for (User user : itUserList) {
if (!mergedUsers.contains(user)) {
mergedUsers.add(user);
}
}
优缺点分析
优点
-
简单易用 :
addAll()
和Stream
的方式非常直观,适合合并一般的 List 数据。 -
灵活性强 :
Stream
API 不仅可以合并,还可以在合并过程中对数据进行操作,如过滤、映射等。 -
性能较好 :在数据量较小时,
addAll()
和Stream
的性能都表现不错。
缺点
- 去重复杂度高 :对于复杂的合并需求,特别是需要去重或根据某些规则合并时,简单的
addAll()
无法满足需求,需要自定义逻辑。 - 内存占用:如果 List 数据量非常大,直接合并可能会导致内存占用过高,需要考虑使用批量处理或分页处理。
核心类方法介绍
addAll(Collection<? extends E> c)
:将指定集合中的所有元素添加到当前集合。Stream.concat(Stream<? extends T> a, Stream<? extends T> b)
:连接两个流,并生成一个包含所有元素的流。Collections.addAll(Collection<? super T> c, T... elements)
:将指定数组的所有元素添加到集合中。
测试用例
测试用例 1:测试 addAll()
方法
测试代码
java
@Test
public void testAddAll() {
List<String> list1 = Arrays.asList("A", "B");
List<String> list2 = Arrays.asList("C", "D");
list1.addAll(list2);
assertEquals(Arrays.asList("A", "B", "C", "D"), list1);
}
代码解析:
如下是具体的代码解析,希望对大家有所帮助:
这段Java代码定义了一个名为 testAddAll
的测试方法,用于验证 List
接口的 addAll
方法是否能够正确地将一个列表中的所有元素添加到另一个列表的末尾。
下面是这段代码的详细解读:
-
@Test
:这是一个JUnit注解,表示标记紧跟其后的方法为测试方法。 -
public void testAddAll() { ... }
:定义了一个名为testAddAll
的测试方法。 -
创建两个列表:
List<String> list1 = Arrays.asList("A", "B");
:创建一个包含 "A" 和 "B" 的列表。List<String> list2 = Arrays.asList("C", "D");
:创建一个包含 "C" 和 "D" 的列表。
-
使用
addAll
方法添加元素:list1.addAll(list2);
:调用list1
的addAll
方法,将list2
中的所有元素添加到list1
的末尾。
-
验证结果:
assertEquals(Arrays.asList("A", "B", "C", "D"), list1);
:使用assertEquals
断言方法验证list1
是否包含所有预期的元素("A"、"B"、"C" 和 "D")。
详细解读:
-
创建测试数据:
- 创建两个列表
list1
和list2
,分别包含字符串 "A"、"B" 和 "C"、"D"。
- 创建两个列表
-
添加元素:
- 使用
list1.addAll(list2)
方法将list2
中的所有元素添加到list1
的末尾。
- 使用
-
验证结果:
- 使用
assertEquals
断言方法验证list1
是否现在包含所有预期的元素。
- 使用
总结:
这个测试用例的目的是确保 List
接口的 addAll
方法能够正确地将一个列表中的元素添加到另一个列表的末尾。通过创建两个列表,使用 addAll
方法将第二个列表的元素添加到第一个列表,然后验证第一个列表的内容是否与预期相匹配,测试确认了 addAll
方法的功能。
注意:代码中使用了 Arrays.asList
方法创建列表,这是Java中一种常见的创建列表的方式。此外,测试方法的名称 testAddAll
表明它专注于测试 addAll
方法的功能。
测试用例 2:测试 Stream.concat()
方法
测试代码
java
@Test
public void testStreamConcat() {
List<String> list1 = Arrays.asList("X", "Y");
List<String> list2 = Arrays.asList("Z");
List<String> mergedList = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());
assertEquals(Arrays.asList("X", "Y", "Z"), mergedList);
}
代码解析:
如下是具体的代码解析,希望对大家有所帮助:这段Java代码定义了一个名为 testStreamConcat
的测试方法,用于验证使用Java 8的Stream API进行列表合并是否正确。
下面是这段代码的详细解读:
-
@Test
:这是一个JUnit注解,表示标记紧跟其后的方法为测试方法。 -
public void testStreamConcat() { ... }
:定义了一个名为testStreamConcat
的测试方法。 -
创建两个列表:
List<String> list1 = Arrays.asList("X", "Y");
:创建一个包含 "X" 和 "Y" 的列表。List<String> list2 = Arrays.asList("Z");
:创建一个包含 "Z" 的列表。
-
使用Stream API合并列表:
Stream.concat(list1.stream(), list2.stream())
:调用Stream.concat
方法,将list1
和list2
转换为流并连接它们。.collect(Collectors.toList())
:使用collect
方法和Collectors.toList()
收集器将合并后的流收集到一个新的列表中。
-
验证结果:
assertEquals(Arrays.asList("X", "Y", "Z"), mergedList);
:使用assertEquals
断言方法验证合并后的列表mergedList
是否与预期的列表(包含 "X"、"Y" 和 "Z")相等。
详细解读:
-
创建测试数据:
- 创建两个列表
list1
和list2
,分别包含字符串 "X"、"Y" 和 "Z"。
- 创建两个列表
-
合并流:
- 使用
Stream.concat
方法将两个列表的流连接起来,创建一个新的流。
- 使用
-
收集结果:
- 使用
collect
方法将合并后的流收集到一个新的列表mergedList
中。
- 使用
-
验证结果:
- 使用
assertEquals
断言方法验证mergedList
是否包含所有预期的元素。
- 使用
总结:
这个测试用例的目的是确保使用Stream API的 Stream.concat
方法能够正确地合并两个列表。通过创建两个列表,将它们转换为流,合并流,然后收集结果到新列表,最后验证结果列表是否与预期相等,测试确认了Stream API的合并功能。
注意:代码中使用了 Arrays.asList
方法创建列表,这是Java中一种常见的创建列表的方式。此外,测试方法的名称 testStreamConcat
表明它专注于测试流合并功能。
小结
本文详细介绍了如何在 Java 中合并多个对象的 List 数据,从最常用的 addAll()
方法到灵活的 Stream
API,再到自定义的合并逻辑。通过多个实际应用案例,展示了合并 List 数据在不同场景中的应用。我们分析了各个方法的优缺点,帮助读者根据需求选择最合适的合并方式。
总结
在 Java 开发中,合并多个对象的 List 数据是常见的操作,掌握不同的合并方法和实现逻辑,能够帮助开发者提高代码效率和可读性。无论是使用简单的 addAll()
,还是灵活的 Stream
,亦或是定制的合并逻辑,开发者都可以根据实际场景灵活运用。
... ...
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
... ...
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。