2009-08-06 28 views
9

Điều tôi cần là bộ sưu tập cho phép nhiều khóa truy cập một đối tượng.Cần một bản đồ/bảng Java có nhiều khóa với một giá trị. Giá trị thường được thay đổi

Tôi cần áp dụng các thay đổi thường xuyên cho đối tượng này.

Nó cũng phải hiệu quả đối với 500 nghìn mục nhập.

+0

Bạn có vô tình đảo ngược câu hỏi của mình không? Vì bạn cho biết "... Bản đồ cho phép một khóa truy cập nhiều giá trị", không đúng với giao diện Bản đồ. Đó là một một ánh xạ giữa khóa và giá trị (mặc dù, tất nhiên, giá trị của bạn có thể là một bộ sưu tập) – Falaina

+0

Khi bạn nói * "thường xuyên thay đổi đối tượng này" * bạn có ý nghĩa gì? Bạn có nghĩa là đối tượng là có thể thay đổi và bạn thay đổi trạng thái của nó? Hoặc bạn có nghĩa là bạn cần phải thay thế một ánh xạ với một ánh xạ khác (và thay thế cho mỗi khóa được liên kết)? –

Trả lời

15

Bất kỳ việc thực hiện java.util.Map<K,V> sẽ làm điều này - có không hạn chế trên bao nhiêu lần một giá trị cụ thể được thêm vào dưới các phím riêng biệt:

Map<String,Integer> m = new HashMap<String, Integer>(); 
m.put("Hello", 5); 
m.put("World", 5); 
System.out.println(m); // { Hello->5, World->5 } 

Nếu bạn muốn có một bản đồ, nơi một chìa khóa duy nhất là liên quan với nhiều giá trị, điều này được gọi là một đa bản đồ và bạn có thể nhận được một từ google java collections API hoặc từ Apache's commons-collections

+3

vấn đề với cách tiếp cận này là bạn không thể nhanh chóng xóa đối tượng khỏi tất cả các khóa được liên kết với nó – njzk2

+0

@ njzk2 không nhất thiết phải là một yêu cầu. "Nó phải có hiệu quả cho 500k + mục" là rất mơ hồ. –

3

Uhm ...

Map map = new HashMap(); 
Object someValue = new Object(); 
map.put(new Object(), someValue); 
map.put(new Object(), someValue); 

Bây giờ bản đồ có cùng giá trị hai lần, có thể truy cập qua các khóa khác nhau. Nếu đó không phải những gì bạn đang tìm kiếm, bạn nên làm lại câu hỏi của mình. :)

2

này có thể làm những gì bạn muốn:

import java.util.*; 
class Value { 
    public String toString() { 
     return x.toString(); 
    } 
    Integer x=0; 
} 
public class Main { 
    public static void main(String[] arguments) { 
     Map m=new HashMap(); 
     final Value v=new Value(); 
     m.put(1,v); 
     m.put(2,v); 
     System.out.println(m.get(1)); 
     System.out.println(m.get(2)); 
     v.x=42; 
     System.out.println(m.get(1)); 
     System.out.println(m.get(2)); 
    } 
+0

Hoàn toàn trả lời một câu hỏi tương tự mà tôi có. – elToro

3

tôi loại giải thích yêu cầu của ông khác nhau. Điều gì sẽ xảy ra nếu người ta muốn hai keyets hoàn toàn khác nhau truy cập vào cùng các giá trị cơ bản. Ví dụ:

"Hello" ------| 
        |----> firstObject 
     3  ------| 

    "Monkey" ------| 
        |----> secondObject 
     72  ------| 

     14  -----------> thirdObject 

    "Baseball" ------| 
        |----> fourthObject 
     18  ------| 

Rõ ràng có hai bản đồ, một cho các phím số nguyên và một cho các phím String, không được đi làm, kể từ khi một bản cập nhật trong một bản đồ sẽ không phản ánh trong các bản đồ khác. Giả sử bạn đã sửa đổi Map<String,Object>, cập nhật "Monkey" để ánh xạ tới fifthObject. Kết quả của sửa đổi này là thay đổi Entry<String,Object> trong bản đồ đó, nhưng điều này tất nhiên không có hiệu lực trên bản đồ khác. Vì vậy, trong khi những gì bạn dự định là:

"Monkey" ------| 
        |----> fifthObject 
     72  ------| 

những gì bạn muốn nhận được trong thực tế sẽ là:

"Monkey" -----------> fifthObject 

     72  -----------> secondObject 

những gì tôi làm trong tình huống này là phải có hai bên bản đồ phụ, nhưng thay vào đó làm cho họ nói Map<String, Integer> Tôi sẽ làm cho chúng Map<String, Integer[]>, trong đó mảng được liên kết là mảng đơn thành viên. Lần đầu tiên tôi liên kết một khóa với một giá trị, nếu không có mảng nào tồn tại và khóa trả về null, tôi tạo mảng và kết hợp bất kỳ khóa nào khác mà tôi muốn với nó (trong bản đồ của khóa đó). Sau đó, tôi chỉ sửa đổi nội dung của mảng, nhưng không bao giờ tham chiếu đến mảng đó, và điều này làm việc một sự quyến rũ.

"Monkey" -------> fifthObjectArray ------| 
               |-----> fifthObjectArray[0] 
     72  -------> fifthObjectArray ------| 
+0

Và nó không phải là hai lớp khác nhau bao gồm các phím - hoặc cả hai có thể là chuỗi, ví dụ – fragorl

0

Câu hỏi của bạn thực sự khiến tôi nghĩ đến việc khiến lớp học này xử lý một thứ như vậy. Tôi hiện đang làm việc trên một công cụ trò chơi 2D và câu hỏi của bạn hoàn toàn làm cho tôi nghĩ về chính xác những gì tôi cần.

Bằng cách bạn đã đọc nó, tôi tin những gì bạn muốn là;

Một đối tượng chứa khóa và giá trị, nhưng bạn cũng có thể giữ các giá trị khóa chung (tôi sử dụng đối tượng này đặc biệt để cắt giảm cpu với chi phí sử dụng bộ nhớ nhiều hơn một chút.)

Loại này 'Loại K là loại khóa chính. Kiểu T là kiểu giá trị HashSet.

Cách bạn thực hiện và sử dụng đối tượng này là:

MapValueSet<ObjectType1,ObjectType2> mainmap = new 

MapValueSet<ObjectType1,ObjectType2>() 
HashSet<Integer> tags = new HashSet<Integer>(); 
     public void test(){ 
      ObjectType1 = new ObjectType1(); 
      ObjectType2 = new ObjectType2(); 

      tags.add(mainmap.put(ObjectType1,ObjectType2); 
      mainmap.get(ObjectType1,Integer); 
     } 

Bạn sẽ cần phải giữ các thẻ duy nhất trong một tập hoặc ArrayList trong bất kỳ lớp học mà bạn thực hiện điều này vì nếu bạn trai tôi Bạn không được lưu trữ các thực thể và không biết thực thể nào. Vì vậy, lưu trữ các số nguyên bạn nhận được từ phương thức put() vào một arraylist hoặc set, và lặp qua đó.

Bạn có thể kiểm tra giá trị của Lớp này nếu chúng tồn tại hoặc đối tượng khóa nào được đặt thành giá trị.

Đây là lớp MapValueSet;

import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Map; 

public class MapValueSet<K,T> { 

     Indexer indxK = new Indexer(); 
     Indexer indxT = new Indexer(); 

     Map<K,Integer> kTags = new HashMap<K,Integer>(); 
     Map<T,Integer> tTags = new HashMap<T,Integer>(); 

     Map<Integer,HashSet<Integer>> MapK = new HashMap<Integer,HashSet<Integer>>(); 

     Map<Integer,HashSet<Integer>> MapT = new HashMap<Integer,HashSet<Integer>>(); 

public int put(K k, T t){ 
    int tag = -1; 
    if(!kTags.containsKey(k)){ 
     kTags.put(k, indxK.getNextTag()); 
    } 

    if(!MapK.containsKey(kTags.get(k))){ 
     MapK.put(kTags.get(k), new HashSet<Integer>()); 
    } 

    if(!tTags.containsKey(t)){ 
     tTags.put(t, tag = indxT.getNextTag()); 
    } 

    if(!MapT.containsKey(tTags.get(t))){ 
     MapT.put(tag = tTags.get(t), new HashSet<Integer>()); 
    }  
     MapK.get(kTags.get(k)).add(tTags.get(t)); 
     MapT.get(tag = tTags.get(t)).add(kTags.get(k)); 

    return tag; 
} 

     @SuppressWarnings("unchecked") 
     public T get(K k, int tag){ 
      Object[] tArr = tTags.keySet().toArray(); 
      for(int i = 0; i < tArr.length; i++){ 
       if(tTags.get((T)tArr[i])== tag){ 
        return (T)tArr[i]; 
      } 
      } 
      return null; 
     } 

     public boolean removeAtKey(K k, T t){ 
       int kTag = -1; 
       int tTag = -1; 

       if(kTags.get(k) != null){ 
       kTag = kTags.get(k); 
       } 

       if(tTags.get(t) != null){ 
       tTag = tTags.get(t); 
       } 

       if(kTag == -1 || tTag == -1){ 
         System.out.println("Keys are Blank at: removeAtKey(k,t)"); 
         return false; 
       } 

       boolean removed = false; 

         if(MapK.get(kTag) != null){ 
           removed = MapK.get(kTag).remove(tTag); 
         } 
         if(MapT.get(tTag) != null){ 
           MapT.get(tTag).remove(kTag); 
         } 

         if(!MapK.containsKey(kTag)){ 
           kTags.remove(k); 
           indxK.removeTag(kTag); 
         } 

         if(MapK.containsKey(kTag)){ 
           tTags.remove(t); 
           indxT.removeTag(tTag); 

         } 

       return removed; 
     } 

     public void removeAtValue(T t){ 
       if(!tTags.containsKey(t)){ 
         return; 
       } 
       Object[] keyArr = MapT.get(tTags.get(t)).toArray(); 

       for(int i = 0; i < keyArr.length; i++){ 
         MapK.get(keyArr[i]).remove(tTags.get(t)); 
       } 

         indxT.removeTag(tTags.get(t)); 
         MapT.remove(tTags.get(t)); 
         tTags.remove(t); 
     } 

     public boolean mapContains(T t){ 
       if(tTags.get(t) == null){ 
         return false; 
       } 
       int tTag = tTags.get(t); 

       return MapT.get(tTag) != null && !MapT.get(tTag).isEmpty(); 
     } 

     public boolean containsKey(K k){ 

       if(kTags.get(k) == null){ 
         return false; 
       } 

       return MapK.containsKey(kTags.get(k)); 
     } 

     public boolean keyContains(K k, T t){ 

       if(kTags.get(k) != null && tTags.get(t) != null){ 
         return MapK.get(kTags.get(k)).contains(tTags.get(t)); 
       } 

       return false; 

     } 

     @Override 
     public String toString(){ 

       String s = ""; 

       s = s+ "Key  Map: " + MapK.toString() + "\n"; 
       s = s+ "Value Map: " + MapT.toString() + "\n"; 
       s = s+ "KeyTag Map: " + kTags.toString() + "\n"; 
       s = s+ "ValueTag Map: " + tTags.toString() + "\n"; 
       s = s+ "KeyTag List: " + indxK.activeSet().toString() + "\n"; 
       s = s+ "ValueTag List: " + indxT.activeSet().toString(); 

       return s;    
     } 


} 
Các vấn đề liên quan