2009-08-06 10 views
9

İhtiyacım olan tek bir nesneye birden çok tuşun erişmesini sağlayan bir koleksiyon.Bir değer için birden fazla tuşa sahip bir Java haritası/tablosu gerekir. Değer genellikle değiştirilmiştir

Bu nesneye sık değişiklikler uygulamam gerekiyor.

Ayrıca 500k + girişler için de verimli olmalıdır.

+0

Sorunuzu kazara ters çevirdiniz mi? Çünkü "Harita, bir anahtarın birden fazla değere erişmesini sağlar", ki bu Harita arayüzünde doğru değil. Anahtar ve değer arasında bire bir eşleme (elbette, değeriniz bir koleksiyon olabilir) – Falaina

+0

* "Bu nesneye sık değişiklikler" derken * Tam olarak ne demek istiyorsunuz? Nesnenin değişebilir olduğunu ve devletini değiştirdiğini mi kastediyorsun? Yoksa, bir eşlemeyi bir diğeriyle değiştirmeniz gerekiyor (ve her bir ilişkili anahtar için değiştirilmeli)? –

cevap

15

java.util.Map<K,V> Herhangi uygulama yapacak - herhangi bir kısıtlama belirli bir değer ayrı tuşlar altına eklenebilir kaç kez vardır: Tek bir tuş ilişkili bir harita istiyorsanız

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

birden değerlerle, bu bir çoklu haritası denir ve google java collections API den birini veya Apache's commons-collections

+3

Bu yaklaşımdaki sorun, nesneyi, bir gereksinim olması gerekmeyen – njzk2

+0

@ njzk2 ile ilişkili tüm anahtarlardan hızla kaldıramayacağınızdır. "500k + girişler için verimli olmalı" çok belirsiz. –

3

Uhm dan ...

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

Şimdi harita iki kez aynı değeri içeriyor, farklı tuşlarla erişilebilir. Aradığınız şey bu değilse, sorunuzu tekrar gözden geçirmelisiniz. :)

2

bu istediğini yapabilir: Bir çeşit farklı talebini yorumlanır

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

Tamamen benzer bir soruya cevap verdim. – elToro

3

. Biri, aynı temel değerlere erişmek için tamamen farklı iki tuş takımı isterse ne olur? Örneğin:

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

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

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

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

Açıkçası iki harita, tamsayı anahtarlar için bir ve Dize anahtarları için bir, tek bir harita üzerinde bir güncelleme diğer haritasında yansıtmaz, çünkü işe gitmiyor sahip. FifthObject ile eşleştirmek için "Monkey" ı güncelleyerek Map<String,Object>'u değiştirdiğinizi varsayalım. Bu değişikliğin sonucu, o harita içinde Entry<String,Object> değiştirmektir, ancak bu elbette diğer harita üzerinde hiçbir etkisi yoktur. iken Peki amaçladığınız oldu: Eğer gerçekte ne alacağı

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

bu olacaktır:

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

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

ne bu durumda ne yan haritaların iki tarafını sahip olmaktır, ancak bunun yerine Bunların Map<String, Integer> olduğunu göstererek bunlarla ilişkili dizinin tek bir üye dizisi olduğu Map<String, Integer[]> olmasını sağlayacağım. Bir anahtarı bir değerle ilk kez ilişkilendirdiğimde, henüz bir dizi mevcut değilse ve anahtar null değerini döndürürse, diziyi yaratıyorum ve onunla birlikte olmasını istediğim başka bir anahtarı (bu anahtarın haritasında) ilişkilendiriyorum. Daha sonra, dizinin içeriğini değiştiririm, ancak dizinin kendisine ait referansı asla kullanmaz ve bu bir çekicilik çalışır.

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

Ve iki farklı sınıf olmak zorunda değildir, bunlar da tuş takımını içerir - her ikisi de dizge olabilir, örneğin – fragorl

0

Sorunuz, aslında bu sınıfı böyle bir şeyin üstesinden gelmeyi düşünmemi sağladı. Şu anda 2 boyutlu bir oyun motoru üzerinde çalışıyorum ve sorunuz tamamen ihtiyacım olan şeyi düşünmemi sağladı.

Bu arada, bunu dolduktan sonra, istediğin şeyin olduğuna inanıyorum;

Anahtarları ve değerleri içeren bir nesne ancak aynı zamanda ortak anahtar değerlerini elde edebilirsiniz (Bu nesneyi özellikle CPU'yu biraz daha fazla bellek kullanmanın maliyetini düşürmek için kullanıyorum).

Bu Sınıf 'K Tipi Birincil Anahtar türüdür. T tipi HashSet Değer Türüdür.

bu nesneyi uygulamak ve kullanmak yoludur:

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); 
     } 

Eğer yapmadım çünkü eğer bu uygulamaya herhangi sınıfta bir dizi veya arraylist benzersiz etiketleri tutmak gerekecektir Varlıkları depolayacak ve hangisinin hangisi olduğunu bilmeyeceksin. Bu yüzden, put() yönteminden aldığınız tamsayı bir arraylist veya set'e depolayın ve bunun üzerinden yineleyin.

Varsa bu Sınıf değerlerini veya değerin ayarlandığı anahtar nesneleri kontrol edebilirsiniz.

Sınıf 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;    
     } 


}