2010-04-03 39 views
11

Tôi có đến các lớp học, ClassAClassB và một "nhiều nhiều" AssociationClass. Tôi muốn sử dụng một cấu trúc để giữ các liên kết giữa A và B như tôi có thể biết, đối với mỗi trường hợp của A hoặc B, là các đối tác của chúng.Java nhiều để nhiều hiệp hội đồ

Tôi nghĩ của việc sử dụng một HashMap, với các phím cặp:

Hasmap<Pair<ClassA, ClassB>, AssociationClass> associations; 

Bằng cách này, tôi có thể thêm và loại bỏ một mối liên hệ giữa hai trường hợp của ClassAClassB, và tôi có thể truy vấn một mối quan hệ cho hai trường hợp cụ thể.

Tuy nhiên, tôi bỏ lỡ tính năng nhận tất cả các liên kết được xác định cho một trường hợp cụ thể là ClassA hoặc ClassB.

Tôi có thể làm điều đó bằng vũ lực và lặp qua tất cả các phím của bản đồ để tìm kiếm các liên kết giữa một cá thể cụ thể, nhưng điều này không hiệu quả và không thanh lịch.

Bạn có biết bất kỳ cấu trúc dữ liệu/thư viện miễn phí nào cho phép điều này không? Tôi không muốn phát minh lại bánh xe.

Cảm ơn trước sự giúp đỡ của bạn,

Raphael

NB: Đây không phải là một "cơ sở dữ liệu" câu hỏi. Các đối tượng này là POJO thuần túy được sử dụng để tính toán trực tiếp, tôi không cần những thứ liên tục.

+0

Do các trường hợp cụ thể của ClassA và ClassB có thể có nhiều kết nối AssociationClass họ? – rmarimon

+0

Đó là một câu hỏi hay: Không. Trong trường hợp của tôi, có tối đa một hiệp hội cho mỗi cặp vợ chồng. –

+0

thì không nhiều lắm. – CPerkins

Trả lời

3

Cảm ơn đề xuất của bạn.

Cuối cùng tôi đã tái tạo lại bánh xe ... Tôi đã viết một lớp chung để tổ chức các liên kết. Tôi sử dụng hai bản đồ của bản đồ, được đồng bộ hóa.

Chủ hiệp hội cung cấp các phương pháp sau

void setAssociation(LeftClass left, RightClass right, AssociationClass assoc); 
AssociationClass getAssociation(LeftClass left, RightClass right); 
Map<RightClass, AssociationClass> getAssocationsLeft(LeftClass left); 
Map<LeftClass, AssociationClass> getAssocationsRight(RightClass right); 
void removeAssociation(LeftClass left, RightClass right); 

Đây là mã:

import java.util.HashMap; 

/** This class holds many to many associations between two classes. */ 
public class AssociationHolder<LeftClass, RightClass, AssociationClass> { 

    // ------------------------------------------------------- 
    // Attributes 
    // ------------------------------------------------------- 

    private HashMap<LeftClass, HashMap<RightClass, AssociationClass>> associationsLeft = 
     new HashMap<LeftClass, HashMap<RightClass,AssociationClass>>(); 
    private HashMap<RightClass, HashMap<LeftClass, AssociationClass>> associationsRight = 
     new HashMap<RightClass, HashMap<LeftClass,AssociationClass>>();  

    // ------------------------------------------------------- 
    // Methods 
    // ------------------------------------------------------- 

    /** 
    * Set an association between two instance. 
    * Any prior association is overwritten. 
    */ 
    public void setAssociation(LeftClass left, RightClass right, AssociationClass association) { 

     // Get the map for the left 
     HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left); 

     // No association defined yet for this left key ? => Create new map 
     if (leftMap == null) { 
      leftMap = new HashMap<RightClass, AssociationClass>(); 
      this.associationsLeft.put(left, leftMap); 
     } 

     // Get the map for the right 
     HashMap<LeftClass, AssociationClass> rightMap = this.associationsRight.get(right); 

     // No association defined yet for this right key ? => Create new map 
     if (rightMap == null) { 
      rightMap = new HashMap<LeftClass, AssociationClass>(); 
      this.associationsRight.put(right, rightMap); 
     } 

     // Set the assoication on both maps 
     leftMap.put(right, association); 
     rightMap.put(left, association);   

    } 

    /** @return null if no association found. */ 
    public AssociationClass getAssociation(LeftClass left, RightClass right) { 

     // Use left maps (could have used the right one as well) 
     HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left); 
     if (leftMap == null) return null; 
     return leftMap.get(right); 
    } 

    /** Get all associations defined for a given Left instance. */ 
    public HashMap<RightClass, AssociationClass> getAssociationsLeft(LeftClass left) { 

     HashMap<RightClass, AssociationClass> leftMap = this.associationsLeft.get(left); 

     // No map defined ? return empty one instead of null 
     if (leftMap == null) { 
      return new HashMap<RightClass, AssociationClass>(); 
     } else { 
      return leftMap; 
     } 
    } 

    /** Get all associations defined for a given Right instance. */ 
    public HashMap<LeftClass, AssociationClass> getAssociationsRight(RightClass right) { 

     HashMap<LeftClass, AssociationClass> rightMap = this.associationsRight.get(right); 

     // No map defined ? return empty one instead of null 
     if (rightMap == null) { 
      return new HashMap<LeftClass, AssociationClass>(); 
     } else { 
      return rightMap; 
     } 
    } 

    /** 
    * Remove an association between two instances. 
    */ 
    public void removeAssociation(LeftClass left, RightClass right) { 
     HashMap<RightClass, AssociationClass> leftMap = this.getAssociationsLeft(left); 
     HashMap<LeftClass, AssociationClass> rightMap = this.getAssociationsRight(right); 
     leftMap.remove(right);  
     rightMap.remove(left); 
    } 
} 

Tôi hy vọng điều này có thể giúp một người nào đó trong tương lai.

+0

Cần lưu ý rằng lớp học này không an toàn thread – pulse0ne

0

Sử dụng AssociationClass của bạn, bạn chỉ có thể có ClassA và ClassB cả hai đều chứa một tham chiếu đến AssociationClass:

private AssociationClass association; 

Hoặc, một phương pháp khác nhau ...

ClassA có thể chứa:

private List<ClassB> classBList; 

và ClassB có thể chứa:

private List<ClassA> classAList; 

Bằng cách thực hiện điều này, bạn có thể truy cập các liên kết của mình từ bên trong lớp được liên kết.

+0

Có, nhưng tôi sẽ cần phải giữ chúng được đồng bộ hóa bằng cách nào đó. Tôi nghĩ rằng tôi muốn có một người giữ liên kết độc lập thực hiện công việc một cách riêng biệt. –

+0

Sẽ dễ dàng giữ chúng được đồng bộ hóa. Bạn có thể viết trong logic đó cho thuộc tính setter của bạn. –

1

Có thể Multimap hoặc BiMap từ Google Collections Library có thể làm những gì bạn cần.

+0

Tôi đã xem nó. Điều này sẽ không giúp ích trong trường hợp này, nhưng tôi giữ điều này trong mục yêu thích của tôi. Tôi không biết thư viện này. Điều này có thể hữu ích. Cảm ơn. –

1

Điều này có vẻ giống như sự cố trong đó bạn có dữ liệu bạn muốn sử dụng nhiều khóa. Bạn muốn tìm kiếm theo ClassA và cũng bởi ClassB. Điều này thường dẫn đến nhiều bản đồ trên cùng dữ liệu để mỗi bản đồ giữ một khóa tìm kiếm vào dữ liệu cơ bản. Có lẽ một cái gì đó như thế này sẽ làm việc:

public class Data { 

    public ClassA a; 
    public ClassB b; 
    public AssociationClass association; 

} 

Map<ClassA, Data> aData; 
Map<ClassB, Data> bData; 
Map<AssociationClass, Data> associationData; 

Chèn đi như thế này:

Data data = new Data() 

aData.put(data.a, data); 
bData.put(data.b, data); 
associationData.put(data.association, data); 

Lấy dữ liệu bạn có thể truy vấn mỗi bản đồ để có được những gì bạn muốn.Bạn thậm chí có thể có lớp Pair của bạn như là một chỉ số vào dữ liệu:

Map<Pair<ClassA, ClassB>, Data> pairData; 

Vấn đề với cách tiếp cận này là nếu các dữ liệu cơ bản thay đổi rất nhiều bạn phải chắc chắn rằng tất cả các bản đồ được đồng bộ. Nếu đây chủ yếu là vấn đề chỉ đọc thì bạn tạo bản đồ và sau đó chỉ cần truy vấn một bản đồ có khóa của bạn vào dữ liệu.

+0

Vâng, tôi chắc chắn cần một số bản đồ. Nhưng tôi nghĩ tôi cần hai bản đồ. –

0

rmarimon đúng rằng nó yêu cầu hai bản đồ, nhưng tôi nghĩ bạn muốn A-B, không phải A-dữ liệu và B-dữ liệu.

Vì vậy, bạn chỉ đơn giản là cần hai bản đồ:


    Hashmap bByA = new HashMap(); 
    Hashmap aByB = new HashMap(); 

này cung cấp cho bạn mọi thứ bạn dường như muốn, miễn phí và dễ dàng.

0

Tại sao không đặt bản đồ trong mỗi lớp?

class ClassA { 
    ... 
    private Map<ClassB, AssociationClass> associations 
      = HashMap<ClassB, AssociationClass>(); 
    ... 
} 

class ClassA { 
    ... 
    private Map<ClassA, AssociationClass> associations 
      = HashMap<ClassB, AssociationClass>(); 
    ... 
} 
4

Dưới đây là thực hiện của tôi dựa trên ổi Multimap:

public class ImmutableBiMultimap<K, V> { 
    private final ImmutableSetMultimap<K, V> kToV; 
    private final ImmutableSetMultimap<V, K> vToK; 

    public ImmutableBiMultimap (SetMultimap<K, V> keyToValueMap) { 
     kToV = ImmutableSetMultimap.copyOf(keyToValueMap); 

     SetMultimap<V, K> valueToKeyMap = HashMultimap.create(); 
     for (Entry<K, V> entry : kToV.entries()) { 
      valueToKeyMap.put(entry.getValue(), entry.getKey()); 
     } 

     vToK = ImmutableSetMultimap.copyOf(valueToKeyMap); 
    } 

    public ImmutableSet<V> getValuesForKey(K key) { 
     return kToV.get(key); 
    } 

    public ImmutableSet<K> getKeysForValue(V value) { 
     return vToK.get(value); 
    } 
} 
Các vấn đề liên quan