Java 集合转换
在Java编程过程中,我们经常需要在不同的集合类型之间进行转换。例如,将数组转换为List,将Set转换为List,或者将Map的键或值提取出来等。掌握这些转换技巧对于高效处理数据结构至关重要。
为什么需要集合转换?
集合转换的需求源于不同集合类型的特点和使用场景:
- 不同集合类型有不同的特性和优势
- 某些API可能要求特定类型的集合作为输入或输出
- 在处理数据时,可能需要利用不同集合类型的功能
数组与集合的转换
数组转换为List
将数组转换为List是最常见的操作之一,有多种方法可以实现:
使用Arrays.asList()
java
String[] array = {"Apple", "Banana", "Orange"};
List<String> list = Arrays.asList(array);
System.out.println("原始数组: " + Arrays.toString(array));
System.out.println("转换后的List: " + list);
输出:
原始数组: [Apple, Banana, Orange]
转换后的List: [Apple, Banana, Orange]
注意
Arrays.asList()
返回的List是固定大小的列表,它是数组的视图,不支持添加或删除元素。如果尝试这些操作,会抛出UnsupportedOperationException
异常。
如果需要一个可修改的List,可以使用以下方式:
java
String[] array = {"Apple", "Banana", "Orange"};
List<String> list = new ArrayList<>(Arrays.asList(array));
list.add("Grape"); // 这是允许的
System.out.println("可修改的List: " + list);
输出:
可修改的List: [Apple, Banana, Orange, Grape]
使用Java 8及以上的Stream API
java
String[] array = {"Apple", "Banana", "Orange"};
List<String> list = Arrays.stream(array).collect(Collectors.toList());
System.out.println("通过Stream API转换的List: " + list);
输出:
通过Stream API转换的List: [Apple, Banana, Orange]
List转换为数组
java
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
// 转换为Object数组
Object[] objectArray = list.toArray();
System.out.println("Object数组: " + Arrays.toString(objectArray));
// 转换为指定类型的数组
String[] stringArray = list.toArray(new String[0]);
System.out.println("String数组: " + Arrays.toString(stringArray));
// Java 11及以上可以使用更简洁的写法
// String[] stringArray = list.toArray(String[]::new);
输出:
Object数组: [Apple, Banana, Orange]
String数组: [Apple, Banana, Orange]
集合之间的转换
List转Set
当你需要去除List中的重复元素时,将其转换为Set是很有用的。
java
List<String> fruitList = new ArrayList<>();
fruitList.add("Apple");
fruitList.add("Banana");
fruitList.add("Apple"); // 重复元素
fruitList.add("Orange");
// 将List转换为HashSet
Set<String> fruitSet = new HashSet<>(fruitList);
System.out.println("原始List: " + fruitList);
System.out.println("转换后的Set (去重): " + fruitSet);
输出:
原始List: [Apple, Banana, Apple, Orange]
转换后的Set (去重): [Apple, Orange, Banana]
Set转List
当你需要按特定顺序访问Set中的元素,或者需要使用List特有的方法时,将Set转为List很有用。
java
Set<String> fruitSet = new HashSet<>();
fruitSet.add("Apple");
fruitSet.add("Banana");
fruitSet.add("Orange");
// 将Set转换为ArrayList
List<String> fruitList = new ArrayList<>(fruitSet);
// 现在我们可以对列表进行排序
Collections.sort(fruitList);
System.out.println("原始Set: " + fruitSet);
System.out.println("转换后并排序的List: " + fruitList);
输出:
原始Set: [Apple, Orange, Banana]
转换后并排序的List: [Apple, Banana, Orange]
Map相关转换
Map是特殊的集合类型,它存储键值对。我们可以提取Map的键、值或者键值对进行各种操作。
获取Map的键集合
java
Map<String, Integer> fruitPrices = new HashMap<>();
fruitPrices.put("Apple", 100);
fruitPrices.put("Banana", 50);
fruitPrices.put("Orange", 80);
// 获取键的Set
Set<String> fruitNames = fruitPrices.keySet();
System.out.println("水果名称: " + fruitNames);
输出:
水果名称: [Apple, Orange, Banana]
获取Map的值集合
java
// 获取值的Collection
Collection<Integer> prices = fruitPrices.values();
System.out.println("价格列表: " + prices);
输出:
价格列表: [100, 80, 50]
获取Map的条目集合并转换
java
// 获取键值对的Set
Set<Map.Entry<String, Integer>> entries = fruitPrices.entrySet();
// 将Map转换为包含键值对的List
List<Map.Entry<String, Integer>> entryList = new ArrayList<>(entries);
// 按价格排序
entryList.sort(Map.Entry.comparingByValue());
System.out.println("按价格排序的水果:");
for (Map.Entry<String, Integer> entry : entryList) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
输出:
按价格排序的水果:
Banana: 50
Orange: 80
Apple: 100
使用Stream API进行高级转换
Java 8引入的Stream API提供了更强大和灵活的集合转换方式。
集合到其他集合的转换
java
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange", "Apple");
// List转Set (去重)
Set<String> uniqueFruits = fruits.stream()
.collect(Collectors.toSet());
System.out.println("去重后的水果: " + uniqueFruits);
// 转换为TreeSet (自然排序)
TreeSet<String> sortedFruits = fruits.stream()
.collect(Collectors.toCollection(TreeSet::new));
System.out.println("排序后的水果: " + sortedFruits);
// 转换为LinkedList
LinkedList<String> linkedListFruits = fruits.stream()
.collect(Collectors.toCollection(LinkedList::new));
System.out.println("LinkedList水果: " + linkedListFruits);
输出:
去重后的水果: [Apple, Orange, Banana]
排序后的水果: [Apple, Banana, Orange]
LinkedList水果: [Apple, Banana, Orange, Apple]
转换为Map
java
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange");
// 转换为Map,键为水果名,值为水果名长度
Map<String, Integer> fruitLengths = fruits.stream()
.collect(Collectors.toMap(
fruit -> fruit, // 键映射函数
String::length // 值映射函数
));
System.out.println("水果名称及其长度: " + fruitLengths);
输出:
水果名称及其长度: {Apple=5, Orange=6, Banana=6}
实际应用场景
场景1: 数据过滤和转换
假设我们有一个员工列表,需要筛选出所有工资超过5000的员工,并按照工资降序排列:
java
// 定义员工类
class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() { return name; }
public double getSalary() { return salary; }
@Override
public String toString() {
return name + " ($" + salary + ")";
}
}
// 主程序
public class EmployeeFilter {
public static void main(String[] args) {
// 创建员工列表
List<Employee> employees = Arrays.asList(
new Employee("Alice", 6000),
new Employee("Bob", 4500),
new Employee("Charlie", 7500),
new Employee("David", 5500)
);
// 筛选高薪员工并排序
List<Employee> highPaidEmployees = employees.stream()
.filter(emp -> emp.getSalary() > 5000)
.sorted((e1, e2) -> Double.compare(e2.getSalary(), e1.getSalary()))
.collect(Collectors.toList());
System.out.println("高薪员工(降序排列):");
for (Employee emp : highPaidEmployees) {
System.out.println(emp);
}
}
}
输出:
高薪员工(降序排列):
Charlie ($7500.0)
Alice ($6000.0)
David ($5500.0)
场景2: 分组统计
假设我们有一个订单列表,需要按照客户进行分组并统计每个客户的订单总金额:
java
// 定义订单类
class Order {
private String customer;
private double amount;
public Order(String customer, double amount) {
this.customer = customer;
this.amount = amount;
}
public String getCustomer() { return customer; }
public double getAmount() { return amount; }
}
// 主程序
public class OrderAnalysis {
public static void main(String[] args) {
// 创建订单列表
List<Order> orders = Arrays.asList(
new Order("Customer1", 100.50),
new Order("Customer2", 200.75),
new Order("Customer1", 50.25),
new Order("Customer3", 300.00),
new Order("Customer2", 150.50)
);
// 按客户分组并计算总金额
Map<String, Double> totalByCustomer = orders.stream()
.collect(Collectors.groupingBy(
Order::getCustomer,
Collectors.summingDouble(Order::getAmount)
));
System.out.println("每个客户的订单总金额:");
totalByCustomer.forEach((customer, total) ->
System.out.println(customer + ": $" + total));
}
}
输出:
每个客户的订单总金额:
Customer1: $150.75
Customer2: $351.25
Customer3: $300.0
总结
在Java编程中,集合转换是一项基本且常用的操作:
-
数组与集合的转换:
- 数组转List:
Arrays.asList()
, Stream API - List转数组:
toArray()
,toArray(T[])
- 数组转List:
-
集合之间的转换:
- List转Set:通过构造器创建新集合
- Set转List:通过构造器创建新集合
- Map相关转换:
keySet()
,values()
,entrySet()
-
使用Stream API进行高级转换:
- 使用
collect()
搭配各种Collectors
方法实现复杂转换
- 使用
掌握这些转换技巧可以帮助你更高效地操作数据,让代码更简洁、更易读。
练习
- 编写代码将一个整数数组转换为
List<Integer>
,并移除其中的所有偶数。 - 有一个字符串列表,将其转换为Map,其中键是字符串本身,值是字符串的长度。
- 创建一个包含重复元素的List,将其转换为Set去除重复元素,然后再转换回List并排序。
- 使用Stream API将Map的键和值分别提取为两个单独的List。
进阶学习
要深入学习Java集合转换,建议掌握Java 8的Stream API和函数式编程特性,它们提供了更强大和灵活的数据处理方式。