Soru Java'da rastgele bir HashMap değerini elde etmenin bir yolu var mı?


Java'da rastgele bir HashMap değerini elde etmenin bir yolu var mı?


26
2018-05-30 11:07


Menşei


Niçin buna ihtiyacın var? Testten başka bir şey varsa, yanlış veri yapısını kullanıyorsunuz. Test içinse, muhtemelen rastgele veri istemezsiniz. - kdgregory
Cevabımı aşağıya bakın - bunu yapmanın uygun yolu, koşullarınıza biraz bağlıdır (özellikle, harita üzerinde değişiklik yapmak için kaç tane rastgele öğeye ihtiyacınız var). - Neil Coffey
Verimli bir şey istiyorsanız, cevabımda bir göz atın. stackoverflow.com/questions/9919734/... Hashtables prensipte rasgele elemanlara erişmek için harika bir yapıdır. Java API'sının bunu yapmanın kolay bir yolu olmadığını talihsiz bir durum. - Thomas Ahle
Kdgregory merhaba, eski bir konu olduğunu biliyorum, ama neden yanlış erişim için yanlış veri yapısını söylediğini merak ediyorum? Teşekkürler - RegUser
@RegUser - HashMaps, değer yerine anahtar ile erişilecek şekilde tasarlanmıştır. İki yönlü eşleştirmeler için kullanışlar vardır, ancak bu amaçla tasarlanmış bir sınıf seçmelisiniz ve HashMap'i, yapmak için tasarlanmamış bir şey yapmaya zorlamalısınız. - kdgregory


Cevaplar:


Şunun gibi bir şey kullanabilirsiniz:

Random generator = new Random();
Map.Entry[] entries = myHashMap.entrySet().toArray();
randomValue = entries[generator.nextInt(entries.length)].getValue();

Güncelleştirme.

Yukarıdaki çalışmıyor, Set.toArray() her zaman bir dizi döndürür Objects, bir dizi içine zorlanamaz Map.Entry.

Bu (daha basit sürüm) çalışır:

Random generator = new Random();
Object[] values = myHashMap.values().toArray();
Object randomValue = values[generator.nextInt(values.length)];

Rasgele değerin, Object sadece son satıra bir cast ekleyin. Eğer öyleyse myHashMap şöyle ilan edildi:

Map<Integer,String> myHashMap = new HashMap<Integer,String>();

Son satır şöyle olabilir:

String randomValue = (String) values[generator.nextInt(value.length)];

43
2018-05-30 11:23



kodunuzu çalıştırırken istisna "uyumsuz türler bulundu java.util.object [] ama beklenen java.util.entry []" - Varuna
Gerekli tip dökümü nasıl yapılır? Map.Andry'ye denedim. - Varuna
Merhaba Varuna, sen haklısın, bu kod kırıldı! Cevabım işe yarayan bir kod ekledim. - Tom Jefferys
Coobird tarafından bunun altındaki yazı da doğru ve işe yarıyor Ama bunu doğru çözüm olarak seçiyorum çünkü bu daha basit - Varuna
Yardım ettiğin için teşekkür ederim!!!!!!!! - Varuna


Gereksinimlerden sadece rastgele bir değer istediği için HashMapİşte yaklaşım:

  1. HashMap bir var values bir döndüren yöntem Collection haritadaki değerlerin
  2. Collection oluşturmak için kullanılır List.
  3. size yönteminin boyutunu bulmak için kullanılır Listtarafından kullanılan Random.nextInt rastgele bir dizin almak için yöntem List.
  4. Son olarak, değer List  get rastgele endeksle yöntem.

Uygulama:

HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 10);
map.put("Answer", 42);

List<Integer> valuesList = new ArrayList<Integer>(map.values());
int randomIndex = new Random().nextInt(valuesList.size());
Integer randomValue = valuesList.get(randomIndex);

Bu yaklaşımın güzel tarafı, tüm yöntemlerin genel - typecasting için gerek yoktur.


27
2018-05-30 11:52



Sevgili coobird kodunuz doğru ve işe yarıyor Ama daha önce Tom bana daha basit gibi görüneceği için seçiyorum !!!!! Yardım ettiğin için teşekkür ederim - Varuna


Herhangi bir öğeyi tekrar etmeden haritadan daha fazla değer çizmeniz gerekiyorsa, haritayı bir Liste'ye koyabilir ve daha sonra karıştırabilirsiniz.

List<Object> valuesList = new ArrayList<Object>(map.values());
Collections.shuffle( valuesList );

for ( Object obj : valuesList ) {
    System.out.println( obj );
}

9
2018-05-30 12:29



Collections.shuffle () için +1; Bunu daha önce görmedim. Güzel; Teşekkürler! - Carl Manaster


0 ile aralığındaki anahtar sayısı arasında rastgele bir sayı oluşturun. HashMap. Anahtarı rastgele sayıya getir. Değeri o anahtardan alın.

pseudocode:

 int n =  random(map.keys().length());
 String key = map.keys().at(n);
 Object value = map.at(key);

Bunu Java’da uygulamak zorsa, bu kodu kullanarak toArray() işlevi Set.

 Object[] values = map.values().toArray(new Object[map.size()]);
 Object random_value = values[random(values.length)];

Rasgele sayıyı nasıl yapacağımdan emin değilim.


3
2018-05-30 11:11



Bu, bir Haritanın anahtarları bir Küme olduğundan ve Küme'nin herhangi bir pozisyona sahip olmaması nedeniyle, Java'ya çevrilemez. - kdgregory
Sanırım ikinci fikrim daha iyi çalışacak. - Peter Stuifzand
İndirgemeyi kaldırmak doğru yöntemleri aradınız çünkü (hala OP'nin sorunu yeniden düşünmesi gerektiğini düşünüyorum). Rastgele sayı için java.lang.Random bir göz atın. - kdgregory


İyi bir cevap, özellikle de belirli bir harita için hangi sıklıkla rastgele bir anahtar almanız gerektiğine bağlıdır (N.B. Bu teknik, anahtar veya değer alırken esas olarak aynıdır).

  • Eğer ihtiyacın varsa çeşitli rasgele anahtarlar belirli bir haritadan harita olmadan değiştirme almak arasında rastgele tuşlar rasgele örnekleme yöntemi tekrar söylediğin gibi Anahtar kümesi aracılığıyla. Etkili ne yaptığınız set üzerinde yinelemek keySet () tarafından döndürülen ve her biri madde olasılığını hesaplamak o anahtarı almak isteyen nasıl Genelde ihtiyacınız olacak ve Şimdiye kadar çektiğiniz numara. Sonra rastgele bir sayı oluşturmak ve bu sayıdan daha düşük olasılık. (N.B. Bu yöntem her zaman çalışırSadece 1 tuşa ihtiyacınız olsa bile; Bu durumda mutlaka en etkili yol değil.)
  • HashMap'taki tuşlar etkili bir şekilde zaten sahte rasgele sırayla. Bir Olacak en büyük durum bir tek Hiç bir rasgele anahtar ihtiyacı bir için olası harita verildiğinde, sadece dışarı çekin ilk unsuru anahtar seti().
  • İçinde diğer durumlar (ya sen birden fazla olası rastgele anahtarlara ihtiyaç duyar belirli bir harita veya harita için rastgele alırken değişecek anahtarlar), esas olarak bir dizi / liste oluştur veya sürdürSeçtiğiniz tuşların rastgele anahtar.

1
2018-05-30 13:07



... OP'in anahtarlar değil rastgele değerler istediği hariç - kdgregory
Üzgünüm, anahtar ya da değeri alıp almamanıza rağmen, aynı şey geçerlidir. - Neil Coffey


Bunu neden yapmak istediğini gerçekten bilmiyorum ... ama yardımcı oluyorsa, değerleri () çağırdığınızda değerleri otomatik olarak rasgele hale getiren bir RandomMap oluşturdum, ardından aşağıdaki runnable demo uygulaması işi yapabilir. .

  package random;

  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;

  public class Main {
      public static void main(String[] args) {
          Map hashMap = makeHashMap();
          // you can make any Map random by making them a RandomMap
          // better if you can just create the Map as a RandomMap instead of HashMap
          Map randomMap = new RandomMap(hashMap);

          // just call values() and iterate through them, they will be random
          Iterator iter = randomMap.values().iterator();

          while (iter.hasNext()) {
              String value = (String) iter.next();
              System.out.println(value);
          }
      }

      private static Map makeHashMap() {
          Map retVal;

          // HashMap is not ordered, and not exactly random (read the javadocs)
          retVal = new HashMap();

          // TreeMap sorts your map based on Comparable of keys
          retVal = new TreeMap();

          // RandomMap - a map that returns stuff randomly
          // use this, don't have to create RandomMap after function returns
          // retVal = new HashMap();

          for (int i = 0; i < 20; i++) {
              retVal.put("key" + i, "value" + i);
          }

          return retVal;
      }
  }

  /**
   * An implementation of Map that shuffles the Collection returned by values().
   * Similar approach can be applied to its entrySet() and keySet() methods.
   */
  class RandomMap extends HashMap {
      public RandomMap() {
          super();
      }

      public RandomMap(Map map) {
          super(map);
      }

      /**
       * Randomize the values on every call to values()
       *
       * @return randomized Collection
       */
      @Override
      public Collection values() {
          List randomList = new ArrayList(super.values());
          Collections.shuffle(randomList);

          return randomList;
      }

  }

0
2018-05-30 12:14





Burada Peter Stuifzand tarafından tanımlanan diziler yaklaşımının nasıl kullanılacağı ile ilgili bir örnek verilmiştir. values()-yöntem:

// Populate the map
// ...

Object[] keys = map.keySet().toArray();
Object[] values = map.values().toArray();

Random rand = new Random();

// Get random key (and value, as an example)
String randKey = keys[ rand.nextInt(keys.length) ];
String randValue = values[ rand.nextInt(values.length) ];

// Use the random key
System.out.println( map.get(randKey) );

0
2018-05-30 12:04



Bu, rastgele bir anahtar ve değer döndürür, ancak haritada anahtar-değer eşlemesi olan bir çift değil! - Sean Owen
Evet, ancak örnek, anahtarların ve değerlerin nasıl rasgele hale getirileceğini göstermekti (bkz. :) Yine de örneği açıklayacağım. - MH114
(Kazar'ın anlamı üstte "post") değişti ..;) - MH114


Genellikle gerçekten istemiyorsun rasgele değer değil, sadece herhangi değer ve sonra bunu yapmak güzel:

Object selectedObj = null;
for (Object obj : map.values()) {
    selectedObj = obj;
    break;
}

0
2018-05-07 12:07





Bir diziye dönüştürülür ve daha sonra sıcak yoldayken değeri almak çok yavaş olur.

set (ya da anahtar veya set değeri set) olsun ve böyle bir şey yapın:

    public class SetUtility {
        public static<Type> Type getRandomElementFromSet(final Set<Type> set, Random random) {
        final int index = random.nextInt(set.size());

        Iterator<Type> iterator = set.iterator();

        for( int i = 0; i < index-1; i++ ) {
            iterator.next();
        }

        return iterator.next();
    }

0
2018-05-29 19:30





Bir haritadan, giriş kümesinden veya yineleyiciden rasgele bir giriş, anahtar veya değer almak için bir yardımcı program yazdım.

Bir yineleyicinin boyutunu anlayamayacağınız ve edemediğinizden (Guava bunu yapabilir) aşırı yüklemeniz gerekecek randEntry() Girişlerin uzunluğu olmalıdır bir boyutu kabul etmek için yöntem.

package util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapUtils {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>() {
            private static final long serialVersionUID = 1L;
            {
                put("Foo", 1);
                put("Bar", 2);
                put("Baz", 3);
            }
        };

        System.out.println(randEntryValue(map));
    }

    static <K, V> Entry<K, V> randEntry(Iterator<Entry<K, V>> it, int count) {
        int index = (int) (Math.random() * count);

        while (index > 0 && it.hasNext()) {
            it.next();
            index--;
        }

        return it.next();
    }

    static <K, V> Entry<K, V> randEntry(Set<Entry<K, V>> entries) {
        return randEntry(entries.iterator(), entries.size());
    }

    static <K, V> Entry<K, V> randEntry(Map<K, V> map) {
        return randEntry(map.entrySet());
    }

    static <K, V> K randEntryKey(Map<K, V> map) {
        return randEntry(map).getKey();
    }

    static <K, V> V randEntryValue(Map<K, V> map) {
        return randEntry(map).getValue();
    }
}

0
2018-02-23 18:41