Java - 将对象列表映射到包含其属性属性值的列表

mga*_*mer 34 java properties list

我有如下定义的ViewValue类:

class ViewValue {

private Long id;
private Integer value;
private String description;
private View view;
private Double defaultFeeRate;

// getters and setters for all properties
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中的某处,我需要将ViewValue实例列表转换为包含来自相应ViewValue的id字段值的列表.

我使用foreach循环来做到这一点:

List<Long> toIdsList(List<ViewValue> viewValues) {

   List<Long> ids = new ArrayList<Long>();

   for (ViewValue viewValue : viewValues) {
      ids.add(viewValue.getId());
   }

   return ids;
Run Code Online (Sandbox Code Playgroud)

}

有没有更好的方法来解决这个问题?

Rad*_*nta 34

我们可以使用java 8在一行代码中完成

List<Long> ids = viewValues.stream().map(ViewValue::getId).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

有关更多信息:Java 8 - Streams

  • 好吧,让我直截了当地说:我会添加注释,这是用Java8启用的,这在撰写本文时尚未提供.答案实际上是向7年前所写的内容迈出了一大步. (3认同)

Ulf*_*ack 33

你可以使用Commons BeanUtils和Collections在一行中完成:(
为什么在其他人为你做的时编写自己的代码?)

import org.apache.commons.beanutils.BeanToPropertyValueTransformer;
import org.apache.commons.collections.CollectionUtils;

...

List<Long> ids = (List<Long>) CollectionUtils.collect(viewValues, 
                                       new BeanToPropertyValueTransformer("id"));
Run Code Online (Sandbox Code Playgroud)

  • 评论为+1"为什么在其他人为您完成代码时编写您自己的代码?" 这是我们每天面临的一个问题 - 必须为已经解决的问题创建解决方案. (5认同)
  • 我唯一不喜欢的是缺少类型安全性 - 如果`viewValue.id`字段被重命名,代码仍然会编译但在运行时失败. (4认同)

Prz*_*wak 29

使用谷歌收藏.例:

    Function<ViewValue, Long> transform = new Function<ViewValue, Long>() {
        @Override
        public Long apply(ViewValue from) {
            return from.getId();
        }
    };
    List<ViewValue> list = Lists.newArrayList();
    List<Long> idsList = Lists.transform(list, transform);
Run Code Online (Sandbox Code Playgroud)

更新:

在Java 8上,您不需要Guava.您可以:

import com.example.ViewValue;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

Function<ViewValue, Long> transform = ViewValue::getId;
List<ViewValue> source = new ArrayList<>();
List<Long> result = source.stream().map(transform).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

要不就:

List<ViewValue> source= new ArrayList<>();
List<Long> result = source.stream().map(ViewValue::getId).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

NEXT UPDATE(Javaslang之后的最后一个改名为Vavr):

目前,它是值得一提的关于与解决方案Javaslang库(http://www.javaslang.io/) Vavr库(http://www.vavr.io/).让我们假设我们的列表包含真实对象:

List<ViewValue> source = newArrayList(new ViewValue(1), new ViewValue(2), new ViewValue(2));
Run Code Online (Sandbox Code Playgroud)

我们可以使用Javaslang库中的List类进行转换(从长远来看,收集不方便):

List<Long> result = io.vavr.collection.List.ofAll(source).map(ViewValue::getId).toJavaList();
Run Code Online (Sandbox Code Playgroud)

但是你会看到只有Javaslang列表的力量:

io.vavr.collection.List<ViewValue> source = javaslang.collection.List.of(new ViewValue(1), new ViewValue(2), new ViewValue(3));
io.vavr.collection.List<Long> res = source.map(ViewValue::getId);
Run Code Online (Sandbox Code Playgroud)

我鼓励在该库上查看可用的集合和新类型(我特别喜欢Try类型).您可以在以下地址找到文档:http ://www.javaslang.io/javaslang-docs/ http://www.vavr.io/vavr-docs/.

PS.由于Oracle和名称中的"Java"字,他们必须将库名从javaslang更改为其他名称.他们决定去Vavr.


Jon*_*eet 27

编辑:这个答案是基于你需要为代码中的其他实体和不同属性做类似事情的想法.如果您只需要通过ID将ViewValues列表转换为Longs列表,那么请坚持使用原始代码.但是,如果您想要一个更可重用的解决方案,请继续阅读......

我会声明一个投影界面,例如

public interface Function<Arg,Result>
{
    public Result apply(Arg arg);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以编写一个通用的转换方法:

public <Source, Result> List<Result> convertAll(List<Source> source,
    Function<Source, Result> projection)
{
    ArrayList<Result> results = new ArrayList<Result>();
    for (Source element : source)
    {
         results.add(projection.apply(element));
    }
    return results;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样定义简单的投影:

private static final Function<ViewValue, Long> ID_PROJECTION =
    new Function<ViewValue, Long>()
    {
        public Long apply(ViewValue x)
        {
            return x.getId();
        }
    };
Run Code Online (Sandbox Code Playgroud)

并像这样应用它:

List<Long> ids = convertAll(values, ID_PROJECTION);
Run Code Online (Sandbox Code Playgroud)

(显然使用K&R支撑和更长的线条使投影声明更短:)

坦率地说,所有这些对于lambda表达式来说会更好,但没关系......

  • 非常Javaesque解决方案 - 但不是很好.它并没有完全减少代码的数量或复杂性,是吗? (5认同)