
本文详细介绍了如何利用java stream api处理嵌套列表数据。以产品图像为例,演示了如何筛选出具有特定类型(如jpg)的图像,并将其url聚合为逗号分隔的字符串。教程涵盖了predicate、map、filter和reduce等核心stream操作,旨在提供一种简洁高效的数据处理方案,适用于复杂对象集合的筛选和数据提取场景。
在日常的软件开发中,我们经常会遇到需要处理复杂数据结构的情况,例如一个对象中包含一个列表,而列表中的每个元素又包含另一个列表。传统的使用循环迭代的方式来筛选和转换这些数据,代码往往冗长且难以维护。Java 8引入的Stream API提供了一种声明式、函数式的方法来处理集合数据,极大地简化了这类操作。
本教程将以一个具体场景为例,演示如何利用Java Stream API高效地从嵌套列表中筛选出符合特定条件的数据,并将其聚合为所需的格式。
假设我们有一个产品数据模型,其中每个产品包含一个图片列表。每张图片又可以有多种格式(如JPG、PNG、MP4)。我们的目标是:从给定的一组图片中,筛选出所有类型包含“JPG”的图片,并将其URL地址以逗号分隔的字符串形式返回。
为了更好地模拟这个场景,我们首先定义相应的数据模型。
立即学习“Java免费学习笔记(深入)”;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.BinaryOperator;
import java.util.Arrays;
// 图片格式枚举及类
class ImageFormat {
enum Type { JPG, PNG, MP4 }
Type format;
public ImageFormat(Type format) {
this.format = format;
}
public Type getFormat() {
return format;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImageFormat that = (ImageFormat) o;
return format == that.format;
}
@Override
public int hashCode() {
return Objects.hash(format);
}
@Override
public String toString() {
return format.name();
}
}
// 图片类
class ProductImage {
String id;
String url;
List<ImageFormat> types;
public ProductImage(String id, String url, List<ImageFormat> types) {
this.id = id;
this.url = url;
this.types = types;
}
public String getUrl() {
return url;
}
public List<ImageFormat> getTypes() {
return types;
}
@Override
public String toString() {
return "ProductImage{" +
"id='" + id + '\'' +
", url='" + url + '\'' +
", types=" + types +
'}';
}
}
// 产品类 (包含图片列表)
class Product {
String name;
List<ProductImage> images;
public Product(String name, List<ProductImage> images) {
this.name = name;
}
public List<ProductImage> getImages() {
return images;
}
}我们将分步构建Stream管道,以实现上述目标。
首先,我们需要一个 Predicate 来判断一个 ProductImage 对象是否包含 JPG 格式。由于 types 是一个列表,我们需要在内部使用 anyMatch 来检查是否存在匹配项。
// 定义一个 Predicate,用于判断图片是否包含 JPG 格式
static final Predicate<ProductImage> isJpgImage = (image) ->
image.getTypes().stream()
.anyMatch(format -> format.getFormat() == ImageFormat.Type.JPG);这里的 anyMatch 方法非常关键,它允许我们在Stream的内部对嵌套列表进行条件判断,只要有一个元素满足条件,anyMatch 就会返回 true。
接下来,我们需要一个 BinaryOperator 来将Stream中的字符串元素(即URL)聚合为一个逗号分隔的字符串。
// 定义一个 BinaryOperator,用于将字符串用逗号连接起来 static final BinaryOperator<String> urlReducer = (a, b) -> a + "," + b;
现在,我们可以将上述组件组合起来,构建完整的Stream管道。
public static String getJpgImageUrls(final List<ProductImage> images) {
return images.stream()
.filter(isJpgImage) // 步骤1:筛选出包含JPG格式的图片
.map(ProductImage::getUrl) // 步骤2:将筛选出的图片映射为其URL
.reduce(urlReducer) // 步骤3:将所有URL聚合为逗号分隔的字符串
.orElse("No matching JPG images found."); // 处理没有匹配项的情况
}为了方便测试和理解,我们提供一个完整的示例类,包含数据初始化和调用逻辑。
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.BinaryOperator;
import java.util.Arrays;
// 图片格式枚举及类
class ImageFormat {
enum Type { JPG, PNG, MP4 }
Type format;
public ImageFormat(Type format) {
this.format = format;
}
public Type getFormat() {
return format;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImageFormat that = (ImageFormat) o;
return format == that.format;
}
@Override
public int hashCode() {
return Objects.hash(format);
}
@Override
public String toString() {
return format.name();
}
}
// 图片类
class ProductImage {
String id;
String url;
List<ImageFormat> types;
public ProductImage(String id, String url, List<ImageFormat> types) {
this.id = id;
this.url = url;
this.types = types;
}
public String getUrl() {
return url;
}
public List<ImageFormat> getTypes() {
return types;
}
@Override
public String toString() {
return "ProductImage{" +
"id='" + id + '\'' +
", url='" + url + '\'' +
", types=" + types +
'}';
}
}
// 产品类 (包含图片列表) - 示例中直接处理图片列表,产品类可简化
class Product {
String name;
List<ProductImage> images;
public Product(String name, List<ProductImage> images) {
this.name = name;
this.images = images;
}
public List<ProductImage> getImages() {
return images;
}
}
public class NestedListStreamProcessor {
// 定义一个 Predicate,用于判断图片是否包含 JPG 格式
static final Predicate<ProductImage> isJpgImage = (image) ->
image.getTypes().stream()
.anyMatch(format -> format.getFormat() == ImageFormat.Type.JPG);
// 定义一个 BinaryOperator,用于将字符串用逗号连接起来
static final BinaryOperator<String> urlReducer = (a, b) -> a + "," + b;
/**
* 从图片列表中获取所有包含JPG格式的图片的URL,并以逗号分隔。
*
* @param images 图片列表
* @return 逗号分隔的JPG图片URL字符串,如果没有匹配项则返回 "No matching JPG images found."
*/
public static String getJpgImageUrls(final List<ProductImage> images) {
return images.stream()
.filter(isJpgImage) // 筛选出包含JPG格式的图片
.map(ProductImage::getUrl) // 将筛选出的图片映射为其URL
.reduce(urlReducer) // 将所有URL聚合为逗号分隔的字符串
.orElse("No matching JPG images found."); // 处理没有匹配项的情况
}
public static void main(String[] args) {
// 构造示例数据
List<ProductImage> productAImages = Arrays.asList(
new ProductImage("img1", "url1", Arrays.asList(
new ImageFormat(ImageFormat.Type.JPG),
new ImageFormat(ImageFormat.Type.PNG)
)),
new ProductImage("img2", "url2", Arrays.asList(
new ImageFormat(ImageFormat.Type.MP4),
new ImageFormat(ImageFormat.Type.PNG)
)),
new ProductImage("img3", "url3", Arrays.asList(
new ImageFormat(ImageFormat.Type.JPG),
new ImageFormat(ImageFormat.Type.MP4)
))
);
System.out.println("产品A的图片列表:");
productAImages.forEach(System.out::println);
System.out.println("\n----------------------------------------");
// 调用方法获取JPG图片URL
String jpgUrls = getJpgImageUrls(productAImages);
System.out.println("产品A中JPG图片URL (逗号分隔): " + jpgUrls); // 预期输出: url1,url3
System.out.println("\n----------------------------------------");
// 测试没有匹配项的情况
List<ProductImage> noJpgImages = Arrays.asList(
new ProductImage("img4", "url4", Arrays.asList(
new ImageFormat(ImageFormat.Type.PNG)
)),
new ProductImage("img5", "url5", Arrays.asList(
new ImageFormat(ImageFormat.Type.MP4)
))
);
System.out.println("没有JPG图片的产品列表:");
noJpgImages.forEach(System.out::println);
System.out.println("\n----------------------------------------");
String noMatchUrls = getJpgImageUrls(noJpgImages);
System.out.println("没有JPG图片的产品URL (逗号分隔): " + noMatchUrls); // 预期输出: No matching JPG images found.
}
}通过本教程,我们学习了如何利用Java Stream API处理嵌套列表的复杂数据筛选和聚合任务。Stream API提供了一种强大且富有表现力的方式来编写简洁、高效、易于理解的代码。掌握 filter、map、reduce 以及 anyMatch 等核心操作,能够帮助开发者更优雅地处理各种集合操作,显著提升开发效率和代码质量。
以上就是使用Java Stream处理嵌套列表:按条件筛选并聚合数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号