V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rqxiao
V2EX  ›  程序员

Java 有没有这样 List<A>转成 List<B>的工具或者方法可以分享下

  •  
  •   rqxiao · 2019-09-11 17:40:21 +08:00 · 8558 次点击
    这是一个创建于 1898 天前的主题,其中的信息可能已经有所发展或是发生改变。

    B 的属性都来自于 A 中,而且只会比 A 少,属性名也一样

    输入 List , B 输出 List

    33 条回复    2019-09-13 09:41:50 +08:00
    jorneyr
        1
    jorneyr  
       2019-09-11 17:48:09 +08:00
    List<B> listB = listA.stream().map(e => { B b = new B(); BeanUtils.copyProperties(e, b); return b; }).collect(Collectors.toList());

    大概就是这么个样子
    colincat
        3
    colincat  
       2019-09-11 18:10:52 +08:00 via iPhone
    Mapstruct
    wysnylc
        4
    wysnylc  
       2019-09-11 18:13:12 +08:00
    @jorneyr #1 写得没毛病,但是 beanUtils 我建议还是手写 set 因为 copyProperties 对于属性名和类型都有要求而且 spring 和 apache 的规则还不一样,所以最后你会发现还是手动 set 得了
    Ravenddd
        5
    Ravenddd  
       2019-09-11 18:16:10 +08:00 via Android
    笨方法,转成 json 再转 bean
    ilotuo
        6
    ilotuo  
       2019-09-11 18:18:35 +08:00
    1L 手打的吧 "=>" 错了
    简版:
    List<B> listB = listA.stream().mapToObj(B::new).collect(Collectors.toList());
    luozic
        7
    luozic  
       2019-09-11 18:27:23 +08:00 via iPhone
    先转 jsonstring 或者其他序列化的东西再转
    zjp
        8
    zjp  
       2019-09-11 18:38:23 +08:00 via Android
    Dozer 不过已经好几年没有更新了,效率一般
    no1xsyzy
        9
    no1xsyzy  
       2019-09-11 18:46:24 +08:00   ❤️ 1
    1. 写成 Haskell 风格函数签名:(A -> B) -> [A] -> [B]

    2. 丢进 hoogle 你就知道这玩意叫做 map:<https://hoogle.haskell.org/?hoogle=%28A+-%3E+B%29+-%3E+%5BA%5D+-%3E+%5BB%5D&scope=set%3Astackage>

    3. 然后去查 Java 里 map 怎么用
    kaedea
        10
    kaedea  
       2019-09-11 18:51:49 +08:00
    函数式编程里的集合操作符了解一下,对应 Java 的实现就是 Stream#map 这个操作符
    kaedea
        11
    kaedea  
       2019-09-11 18:52:57 +08:00
    顺便说一下 Stream 是 Java 8 开始才支持的特性,如果在 Java 8 以前,可以使用类似的 Stream 库,比如 Eclipse 家的,或者直接上 RxJava 也行
    trait
        12
    trait  
       2019-09-11 18:55:33 +08:00
    list_a.iterate().map(|a| a.to_b())
    xuanbg
        13
    xuanbg  
       2019-09-11 18:57:42 +08:00
    Json.toObject(Json.toJson(a), B.class);
    aguesuka
        14
    aguesuka  
       2019-09-11 19:02:29 +08:00 via Android
    有继承关系吗?没有只能依赖反射。lst.stream().map(funcA2B).collect(toList)
    jamesxu
        15
    jamesxu  
       2019-09-11 19:07:27 +08:00 via iPhone
    dozer 或者 modelmapper
    francis59
        16
    francis59  
       2019-09-11 19:07:56 +08:00
    可以试试 orika-mapper: https://github.com/orika-mapper/orika
    HangoX
        17
    HangoX  
       2019-09-11 19:11:50 +08:00
    自己写个反射拷贝就好了
    hantsy
        18
    hantsy  
       2019-09-12 07:28:10 +08:00
    ModelMapper
    luckylo
        19
    luckylo  
       2019-09-12 07:53:35 +08:00 via Android
    @jorneyr 不建议用 BeanUtils ( spring 包下的)。反正我是莫名其妙的遇见一次效率问题。最后还是手动 setter 好的。

    #3 3 楼的 Mapstruct 听说是个不错选择,还没试过
    vanillaxxx
        20
    vanillaxxx  
       2019-09-12 08:45:06 +08:00 via iPhone
    map 操作符……我半个全栈经常遇到你这种问题,无疑 map 是最方便的
    jorneyr
        21
    jorneyr  
       2019-09-12 09:00:42 +08:00
    @ilotuo 哈哈,最近在写 JS,-> 和 JS 的 => 搞混了。
    rqxiao
        22
    rqxiao  
    OP
       2019-09-12 09:09:00 +08:00
    @ilotuo stream().mapToObj 怎么没这方法
    zhaorunze
        23
    zhaorunze  
       2019-09-12 09:31:48 +08:00
    List<A> = (List)(Object)List<B>
    notreami
        24
    notreami  
       2019-09-12 09:55:56 +08:00
    必须 orika 啊
    rqxiao
        25
    rqxiao  
    OP
       2019-09-12 10:19:17 +08:00
    @zhaorunze 这样不行吧,实际上没有转成 List<A> 还是 List<B>
    xiaoyaojc
        26
    xiaoyaojc  
       2019-09-12 10:46:17 +08:00
    首先要看 a 和 b 的内容,是不是可以直接 copy 的,如果是,直接 copy 属性,如果不是,那只能手动 set 了。
    if (CollectionUtils.isEmpty(sourceList)) {
    return Lists.newArrayList();
    }
    List<T> resultList = Lists.newArrayListWithCapacity(sourceList.size());
    for (Object source : sourceList) {
    try {
    T target = targetClass.newInstance();
    copy(source, target);
    resultList.add(target);
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    return resultList;
    xiaoyaojc
        27
    xiaoyaojc  
       2019-09-12 10:47:57 +08:00
    其中 copy 用 BeanCopier,一般用于对象转换,比如 DO 转 BO 等等。B 的属性都来自于 A 中,而且只会比 A 少,属性名也一样,你的这种情况用 copy 绝对是最快的,不用转 json。转 json 反而慢
    jsnjfz
        28
    jsnjfz  
       2019-09-12 11:09:06 +08:00
    可以看看 guava 中有没工具类
    zhaorunze
        29
    zhaorunze  
       2019-09-12 11:17:19 +08:00   ❤️ 1
    @rqxiao 你试一下再说啊
    luckylo
        30
    luckylo  
       2019-09-12 12:35:03 +08:00 via Android
    @zhaorunze java8 貌似没有,好像在 java11 里面有
    rqxiao
        31
    rqxiao  
    OP
       2019-09-12 13:41:06 +08:00
    @zhaorunze 试过了啊 List<A> 里面的元素属性 实际上都是 B 的属性,
    ixx
        32
    ixx  
       2019-09-12 14:14:50 +08:00
    共有属性放在 B 中,A extents B 同时添加多出来的字段 ,剩下的直接转就行了
    mangodai
        33
    mangodai  
       2019-09-13 09:41:50 +08:00
    bean copy util 都有的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3985 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 05:28 · PVG 13:28 · LAX 21:28 · JFK 00:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.