【问题标题】:How to transform List<X> to another List<Y> [duplicate]如何将 List<X> 转换为另一个 List<Y> [重复]
【发布时间】:2011-11-15 01:34:50
【问题描述】:

我有两个对象列表; List&lt;X&gt;List&lt;Y&gt;XY 是看起来像这样的项目:

public class X {
    String a;
    String b;
    String v;
    String w;
    String m;
    String n;
}

public class Y {
    String a;
    String b;
    List<A> aList;
}
public class A {
    String v;
    String w;
    List<B> bList;
}
public class B {
    String m;
    String n;
}

如何根据规则将List&lt;X&gt; 转换为List&lt;Y&gt;
某些字段的值必须相等。
例如:
List&lt;Y&gt; 中,对于一个对象 Y,字段 a 的值必须相等。
在Y的字段List&lt;A&gt;中,对于一个对象A,字段w的值必须相等。
在A的字段List&lt;B&gt;中,对于一个对象B,字段m的值必须相等,以此类推。

Guava有这个方法,Lists#transform,但是不知道怎么改造。

或者其他方式?

【问题讨论】:

  • 1) 你说“字段a的值必须相等”?等于什么? 2) 如果不满足这些条件会怎样?
  • 我认为这种级别的转换没有任何内置功能。您只需要循环并检查自己。
  • "字段 a 的值必须相等",如 List 到 List,X 的字段 a 必须等于 Y 的字段 a,X 的字段 w 必须等于对象 Y 中 A 的字段 w 等等...并且条件无法满足,因为如果 a 为空,则只是一个新的 Y,其为空字段 a。
  • 仍然没有意义。你在Y 中有List&lt;A&gt;,这个列表应该有多少个A 对象?如果不止一个,它们是否都采用相同的值?
  • 好吧,让我们让它更容易理解。 X是数据库中的一个表,我想把它转换成三个表,表的关系就像Y。我使用hibernate。这就是主键和外键的关系。因为我不会设计表,表 A 中的某些列可能会在 B 或 Y 中发生变化,所以我想要这个转换的函数级别,如果有变化,很容易重建和重新分组。

标签: java list transform guava


【解决方案1】:
public static <F,T> List<T> transform(List<F> fromList,
                                      Function<? super F,? extends T> function

您可能想阅读Lists.transform()Function 的API 文档,但基本上转换的调用者提供了一个Function 对象,该对象将F 转换为T

例如,如果您有一个 List&lt;Integer&gt; intList 并且您想创建一个 List&lt;String&gt; 以便后者的每个元素都包含该数字的英文表示(1 变为“一”等)并且您可以访问类如IntToEnglish then

Function<Integer, String> intToEnglish = 
    new Function<Integer,String>() { 
        public String apply(Integer i) { return new IntToEnglish().english_number(i); }
    };

List<String> wordsList = Lists.transform(intList, intToEnglish);

进行转换。

您可以应用相同的模式将您的List&lt;X&gt; 转换为List&lt;Y&gt;

【讨论】:

  • 不确定是否能解决问题,但非常令人印象深刻
  • 你指的是哪个api文档?
  • 这里有一个需要注意的有趣问题:transform 返回原始列表的视图,它仍然链接到原始列表,并且不是一个单独的新列表。 IE。如果从转换返回的列表中删除一个元素,它也会从原始列表中删除该元素。刚刚发现我,所以想我会分享:)
  • 注意 - Lists.transform() 是懒惰的!来自 Guava JavaDoc:注意:序列化返回的列表是通过序列化 fromList、其内容和函数来实现的,而不是通过序列化转换后的值。这可能会导致令人惊讶的行为,因此不建议对返回的列表进行序列化。相反,使用 ImmutableList.copyOf(Collection) 复制列表(例如),然后序列化副本。由于这个原因,其他类似的方法根本不实现序列化。
  • @vellotis 和 stephendnicholas,您的 cmets 必须以大写形式包含在此答案中。真的,这根本不是明显的行为。
【解决方案2】:

使用 java lambda:

public static <K,V,Q extends K> List<V> transform( final List<Q> input, final java.util.function.Function<K,V> tfunc ) {
    if( null == input ) {
        return null;
    }
    return input.stream().map(tfunc).collect( Collectors.toList() );
}

您只需要实现: java.util.function.Function

【讨论】:

  • 这很好。使用 Java API 无需安装 Guice。
【解决方案3】:

这个怎么样?

import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

public class GuavaTransform {
    public static void main(String[] args) {
        List<X> xList = new ArrayList<X>();
        xList.add(new X("a", "b", "v", "w", "m", "n"));
        xList.add(new X("a1", "b1", "v1", "w1", "m1", "n1"));
        for(X elem: xList) {
            System.out.println("An instance of X:"+ elem);
        }
        System.out.println();
        List<Y> yList = Lists.transform(xList, new TransformXY());
        for(Y elem: yList) {
            System.out.println("The corresponding instance of Y: \n"+elem);
        }
    }
}

class TransformXY implements Function<X, Y> {

    @Override
    public Y apply(X x) {
        List<B> bList = new ArrayList<B>();
        bList.add(new B(x.m, x.n));
        List<A> aList = new ArrayList<A>();
        aList.add(new A(x.v, x.w, bList));
        return new Y(x.a, x.b, aList);
    }
}

class X {
    String a;
    String b;
    String v;
    String w;
    String m;
    String n;
    X(String a, String b, String v, String w, String m, String n) {
        super();
        this.a = a;
        this.b = b;
        this.v = v;
        this.w = w;
        this.m = m;
        this.n = n;
    }
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        sb.append(a+",");
        sb.append(b+",");
        sb.append(v+",");
        sb.append(w+",");
        sb.append(m+",");
        sb.append(n);
        sb.append(")");
        return sb.toString();
    }
}
class Y {
    String a;
    String b;
    List<A> aList;
    Y(String a, String b, List<A> aList) {
        super();
        this.a = a;
        this.b = b;
        this.aList = aList;
    }
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(a+"\n");
        sb.append(b+"\n");
        for(A elem: aList) {
            sb.append(elem+"\n");
        }
        return sb.toString();
    } 
}
class A {
    String v;
    String w;
    List<B> bList;
    A(String v, String w, List<B> bList) {
        super();
        this.v = v;
        this.w = w;
        this.bList = bList;
    }
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("--------"+v+"\n");
        sb.append("--------"+w+"\n");
        for(B elem: bList) {
            sb.append(elem+"\n");
        }
        return sb.toString();
    }

}
class B {
    String m;
    String n;
    B(String m, String n) {
        super();
        this.m = m;
        this.n = n;
    }
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("----------------"+m+"\n");
        sb.append("----------------"+n+"\n");
        return sb.toString();
    }
}

控制台输出:

An instance of X:(a,b,v,w,m,n)
An instance of X:(a1,b1,v1,w1,m1,n1)

The corresponding instance of Y: 
a
b
--------v
--------w
----------------m
----------------n



The corresponding instance of Y: 
a1
b1
--------v1
--------w1
----------------m1
----------------n1

【讨论】:

  • “番石榴”+1,最好用水果来解释。
【解决方案4】:

与 @Isaace 相同,但使用 lambda 语法(从 this example 获取):

List<X> xList = new ArrayList<>();
List<Y> yList = xList
        .stream()
        .map(n -> someTransformFunc(n))
        .collect(Collectors.toList());

【讨论】:

    【解决方案5】:

    Java 8 风格,IntelliJ IDEA‎ 帮助了我:

    List<X> xList = new ArrayList<>();
    List<Y> yList = xList
            .stream()
            .map(X::getY)
            .collect(Collectors.toList());
    

    【讨论】:

      【解决方案6】:

      假设有两个对象可以相互转换,Coach 和 EntityBase

      1.声明泛型方法

         public static <TSourse, TResult> void ToList(List<TSourse> list, List<TResult> results) {
          if (list.size() > 0) {
              for (TSourse obj : list) {
                  TResult tResult = (TResult) obj;
                  if (tResult == null) {
                      throw new AppException("error....");
                  }
                  results.add(tResult);
              }
          }
      }
      

      2.调用该方法

        List<EntityBase> entityBaseList = new ArrayList<>();
          Coach coach = new Coach();
          coach.setId("123");
          entityBaseList.add(coach);
      
          List<Coach> coachList = new ArrayList<>();
          ToList(entityBaseList, coachList);
          //will complete List<AObj> to another List<BObj>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-01
        • 1970-01-01
        • 2017-07-14
        • 1970-01-01
        • 2019-07-28
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多