代码之家  ›  专栏  ›  技术社区  ›  James McMahon

在Java中从多个列表中提取数据到新的最优雅的方式?

  •  0
  • James McMahon  · 技术社区  · 15 年前

    这可能有点主观,但我经常发现,了解其他开发人员如何处理某些日常细节是非常有趣的。

    我有这样的代码:

    class A {
        public List<SomeType> getOneSet() { ... }
        public List<SomeType> getAnotherSet() { ... }
    }
    
    class B {
        public static OtherType convert(SomeType input) { ... }
    }
    
    // ...
    
    A a = new A();
    List<OtherType> rgResults = new ArrayList<OtherType>();
    

    现在将遵循两个相同的 for 循环,就像这样:

    for (SomeType input : a.getOneSet()) {
        rgResults.add(B.convert(input);
    }
    
    for (SomeType input : a.getAnotherSet()) {
        rgResults.add(B.convert(input);
    }
    

    这是可行的,但当然是代码复制。如果循环中的代码变得稍微复杂一点,或者有两组以上的代码,则不可接受。

    因此,我将循环放入一个函数中,该函数将源列表和目标列表作为参数,但很好奇是否还有其他方法。尤其是当您从不从多个地方调用函数时更合适的方法。

    例如,我希望以下内容不起作用,因为我没有泛型数组:

    for (List<SomeType> rgSrc : new List<SomeType>[] { a.getOneSet(), a.getAnotherSet() } ) {
        for (SomeType src : rgSrc) {
            rgResults.add(B.convert(src));
        }
    }
    
    6 回复  |  直到 15 年前
        1
  •  2
  •   Nick Holt    15 年前

    尝试如下操作:

    interface Getter<E, I> 
    {
      public E get(I item);
    }
    
    public static <T extends Collection<E>, I, E> T convert(T target, Collection<I> source, Getter<E, I> getter)
    {
      for (I item : source)
      {
        target.add(getter.get(item));
      }
    
      return target;
    }
    
    List<String> strings = CollectionUtil.convert(
      new ArrayList<String>(someItems.size)
      someItems,
      new Getter<String, MyClass>() 
      {
        public String get(MyClass item)
        {
          return item.toString();
        }
      }
    );
    

    您只需实现 Getter 根据你想做的谈话而定。

        2
  •  6
  •   Aaron Digulla    15 年前

    尝试 IteratorUtils . 这有一个链接迭代器的方法。

        3
  •  2
  •   Narayan    15 年前

    listutils函数 联合(java.util.list list1,java.util.list list2) 从Apache Commons Collection中,API应执行以下任务:=> union 同样=

        4
  •  2
  •   Cowan    15 年前

    遵循“使用别人的代码”的原则,我认为您将找到最干净的实现 Google Collections' Iterables class .

    你可以这样做:

    for (SomeType input : Iterables.concat(a.getOneSet(), a.getAnotherSet()) {
      rgResults.add(B.convert(input);
    }
    

    或者,如果你把b改写成a Function 和使用 Lists :

    rgResults = Lists.transform(
        Lists.newArrayList(Iterables.concat(a.getOneSet(), a.getAnotherSet()), 
        new B());
    

    你完了!

        5
  •  1
  •   Pablojim    15 年前

    对于完全不使用循环的解决方案,可以使用lambdaj转换功能:

    看见 http://code.google.com/p/lambdaj/wiki/LambdajFeatures

        6
  •  1
  •   Adam Crume    15 年前

    从数组中移除泛型参数,循环应该可以工作(尽管会收到警告):

    for (List<SomeType> rgSrc : new List[] { a.getOneSet(), a.getAnotherSet() } ) {
        for (SomeType src : rgSrc) {
            rgResults.add(B.convert(src));
        }
    }