You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 9中如何利用Stream API将含单一非空值字段的Person对象列表转换为值对象列表

Great question! Let's break this down step by step since you want to use Java's Stream API for the conversion.

Solution Overview

First, we need a target value object class to store the converted results (since you mentioned a "value object list"). Then we'll use the Stream API's map() operation to transform each Person instance, with the core logic being identifying the single initialized non-null value field in each Person.

Step 1: Define the Target Value Object

Create a simple value object to hold the person's name and their corresponding valid value:

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PersonValue {
    // Name of the person
    private String personName;
    // The single initialized value from the Person instance
    private Object effectiveValue;
}

If you need stricter type control, you could use generics or split into subclasses, but this generic version works perfectly for the given requirement.

Step 2: Stream API Conversion Logic

Next, we'll use the Stream API's map() operation to iterate over each Person, find the unique valid value by checking fields in sequence, then map it to a PersonValue:

Basic Implementation

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class PersonConverter {
    public static List<PersonValue> convertToValueObjects(List<Person> personList) {
        return personList.stream()
                .map(person -> {
                    // Use Optional to safely check for non-null reference fields
                    Object effectiveValue = Optional.ofNullable(person.getValue_string())
                            .orElseGet(() -> Optional.ofNullable(person.getValue_integer())
                                    .orElseGet(() -> Optional.ofNullable(person.getValue_text())
                                            // Handle the primitive boolean field (can't be null)
                                            .orElseGet(() -> person.isValue_bool())));

                    return new PersonValue(person.getName(), effectiveValue);
                })
                .collect(Collectors.toList());
    }
}

Key Details:

  • Primitive vs Reference Types: Note that value_bool is a primitive boolean (it can't be null), so we handle it last. Per your description, when all other reference fields are null, this boolean field is the initialized one.
  • Optional Chaining: Using Optional.ofNullable() with chained orElseGet() calls lets us cleanly check each reference field in sequence, avoiding messy nested if-else blocks.

To ensure your input Person list strictly follows the "only one initialized field" rule, add validation before conversion to catch invalid data:

.map(person -> {
    // Count how many fields are non-null/initialized
    long validFieldCount = Stream.of(
            person.getValue_string(),
            person.getValue_integer(),
            person.getValue_text(),
            // Convert primitive boolean to Boolean to include in null check
            Boolean.valueOf(person.isValue_bool())
    ).filter(Objects::nonNull).count();

    if (validFieldCount != 1) {
        throw new IllegalArgumentException(
                String.format("Person '%s' has %d initialized value fields (expected exactly 1)",
                        person.getName(), validFieldCount));
    }

    // Retrieve the effective value (same logic as before)
    Object effectiveValue = Optional.ofNullable(person.getValue_string())
            .orElseGet(() -> Optional.ofNullable(person.getValue_integer())
                    .orElseGet(() -> Optional.ofNullable(person.getValue_text())
                            .orElseGet(() -> person.isValue_bool())));

    return new PersonValue(person.getName(), effectiveValue);
})

Alternative: If value_bool is a Boolean (Reference Type)

If your Person class uses Boolean (instead of primitive boolean) for value_bool, you can simplify both validation and value retrieval since all fields are reference types:

Object effectiveValue = Optional.ofNullable(person.getValue_string())
        .orElseGet(() -> Optional.ofNullable(person.getValue_integer())
                .orElseGet(() -> Optional.ofNullable(person.getValue_text())
                        .orElseGet(() -> person.getValue_bool())));

The validation logic also becomes simpler—no need to convert the boolean to a wrapper type, just pass person.getValue_bool() directly to the stream.


内容的提问来源于stack exchange,提问作者Kirill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:19:10