2012-02-27 9 views
1

Guava APIのすべての機能をまだ学んでいます。これを撮影して、これをどうやって行うかについての示唆があるかどうかを見たいと思っていました。 List <ObjectA>, List<ObjectB>, List<ObjectC>Guava Group By Key

ObjectA { 
    Integer attribute1; 
    String attribute2; 
    …. 
} 
ObjectB { 
    Integer attribute1; 
    String attribute2; 
    …. 
} 
ObjectC { 
    Integer attribute1; 
    String attribute2; 
    …. 
} 

私は、このようにこのような何かを作成attribute1とattribute2ので一緒に3つのリストやグループのオブジェクトを利用したいと思います:

123|”Whatever” : { Object A, ObjectB, ObjectC} 
456|”Something” : { Object A, ObjectB, ObjectC} 

明白* Multimapはある現在の画像は次のようになります帰りは、しかし、これを構築するプロセスは、複数のソリューションを持つことができます。これにアプローチする方法についての考え方?

+2

各リストにはそれぞれの属性の組み合わせが1つありますか?また、3つの "Object"クラスはスーパークラスを共有しますか? –

+0

スーパークラスを共有していてもいなくてもよく、各リストに存在しないかもしれません。 – JustinM

答えて

2

attribute1とattribute2の組み合わせを表すために、カスタムペアクラスでMultimaps.index()を使用します。

/** 
* A "pair" class that contains an {@code attribute1} and an {@code attribute2}. Mainly used as a {@link Map} key. 
*/ 
@Immutable 
public class Attribute1AndAttribute2 { 

    @Nullable 
    private final Integer attribute1; 
    @Nullable 
    private final String attribute2; 

    public Attribute1AndAttribute2(@Nullable Integer attribute1, 
            @Nullable String attribute2) { 
     this.attribute1 = attribute1; 
     this.attribute2 = attribute2; 
    } 

    @Nullable 
    public Integer getAttribute1() { 
     return attribute1; 
    } 

    @Nullable 
    public String getAttribute2() { 
     return attribute2; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj instanceof Attribute1AndAttribute2) { 
      Attribute1AndAttribute2 that = (Attribute1AndAttribute2) obj; 
      return Objects.equal(this.attribute1, that.attribute1) 
        && Objects.equal(this.attribute2, that.attribute2); 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hashCode(attribute1, attribute2); 
    } 

} 


/** 
* Static utility methods pertaining to {@link ObjectA}, {@link ObjectB}, and {@link ObjectC}'s {@code attribute1} and 
* {@code attribute2}. 
*/ 
public final class Attribute1AndAttribute2Utils { 
    private Attribute1AndAttribute2Utils() { /* prevents instantiation */ } 

    public static Multimap<Attribute1AndAttribute2, Object> groupedByAttribute1AndAttribute2(List<ObjectA> as, List<ObjectB> bs, List<ObjectC> cs) { 
     Iterable<Object> abcs = Iterables.concat(as, bs, cs); 
     return Multimaps.index(abcs, Attribute1AndAttribute2ForObjectFunction.INSTANCE); 
    } 

    // enum singleton pattern 
    private enum Attribute1AndAttribute2ForObjectFunction implements Function<Object, Attribute1AndAttribute2> { 
     INSTANCE; 

     @Override 
     public Attribute1AndAttribute2 apply(@Nullable Object object) { 
      if (object instanceof ObjectA) { 
       ObjectA objectA = (ObjectA) object; 
       return new Attribute1AndAttribute2(objectA.attribute1, objectA.attribute2); 
      } else if (object instanceof ObjectB) { 
       ObjectB objectB = (ObjectB) object; 
       return new Attribute1AndAttribute2(objectB.attribute1, objectB.attribute2); 
      } else if (object instanceof ObjectC) { 
       ObjectC objectC = (ObjectC) object; 
       return new Attribute1AndAttribute2(objectC.attribute1, objectC.attribute2); 
      } else { 
       throw new RuntimeException("Object must be ObjectA, ObjectB, or ObjectC, but was " + object); 
      } 
     } 
    } 

} 

次のようなインターフェースを持っていた場合は、コードがたくさんクリーナー/良いだろうということ:

また
public interface HasAttribute1AndAttribute2 { 
    Integer getAttribute1(); 
    String getAttribute2(); 
} 

を、私はattribute1とattribute2のがnullの場合も想定。ヌルでない場合は、ペアクラスを次のように変更することを検討してください。

/** 
* A "pair" class that contains an {@code attribute1} and an {@code attribute2}. Mainly used as a {@link Map} key. 
*/ 
@Immutable 
public class Attribute1AndAttribute2 { 

    @Nonnull 
    private final Integer attribute1; 
    @Nonnull 
    private final String attribute2; 

    public Attribute1AndAttribute2(@Nonnull Integer attribute1, @Nonnull String attribute2) { 
     this.attribute1 = checkNotNull(attribute1); 
     this.attribute2 = checkNotNull(attribute2); 
    } 

    @Nonnull 
    public Integer getAttribute1() { 
     return attribute1; 
    } 

    @Nonnull 
    public String getAttribute2() { 
     return attribute2; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj instanceof Attribute1AndAttribute2) { 
      Attribute1AndAttribute2 that = (Attribute1AndAttribute2) obj; 
      return this.attribute1.equals(that.attribute1) 
        && this.attribute2.equals(that.attribute2); 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hashCode(attribute1, attribute2); 
    } 
} 
+0

ありがとう@Eneveu、もっと静的だったらうまくいくでしょう。それが、オブジェクトの完全な新しいセットを意味し、1:M属性である可能性のある異なるグループ化キーに基づいている場合はどうでしょうか? – JustinM

+0

私はあなたが「ダイナミック」という意味を理解していません。オブジェクトに他の属性がある場合(「attribute3」と「attribute4」と言う)、「Attribute1AndAttribute2」クラスの名前を「MyKey」に変更し、「attribute3」フィールドと「attribute4」フィールドを追加します(equals/hashCodeの更新)。あなたのオブジェクトはどのように見えますか? –

+0

ダイナミック - 1:Mオブジェクトと1:Mキーのリストを扱うことができるユーティリティメソッドの詳細。すべてのオブジェクトが属性1または属性2を持つわけではありません。それは理にかなっていますか? – JustinM