有没有办法在Java中随机获取HashMap的值?

有没有办法在Java中随机获取HashMap的值?

你可以使用类似的东西:

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

更新。

上面不起作用Set.toArray()总是返回一个Object数组,它不能被强制转换为Map.Entry数组。

这个(更简单的版本)确实有效:

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

如果您希望随机值是Object以外的类型,只需将转换添加到最后一行。 因此,如果myHashMap被声明为:

 Map myHashMap = new HashMap(); 

最后一行可以是:

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

由于要求只要求来自HashMap的随机值,这里的方法是:

  1. HashMap有一个values方法,它返回map中值的Collection
  2. Collection用于创建List
  3. size方法用于查找List的大小, Random.nextInt方法使用它来获取List的随机索引。
  4. 最后,使用随机索引从List get方法中检索该值。

执行:

 HashMap map = new HashMap(); map.put("Hello", 10); map.put("Answer", 42); List valuesList = new ArrayList(map.values()); int randomIndex = new Random().nextInt(valuesList.size()); Integer randomValue = valuesList.get(randomIndex); 

关于这种方法的好处是所有方法都是通用的 – 不需要进行类型转换。

如果您需要从地图中绘制更多的值而不重复任何元素,您可以将地图放入List中然后随机播放。

 List valuesList = new ArrayList(map.values()); Collections.shuffle( valuesList ); for ( Object obj : valuesList ) { System.out.println( obj ); } 

生成0和HashMap中键数之间的随机数。 获取随机数的密钥。 从该键获取值。

伪代码

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

如果在Java中很难实现它,那么您可以使用SettoArray()函数从此代码创建和数组。

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

我不确定如何做随机数。

一个好的答案略微取决于具体情况,特别是你需要为给定地图获取随机密钥的频率(注意,无论你采用密钥还是值,技术基本相同)。

  • 如果您需要来自给定地图的各种随机密钥在获取随机密钥之间不会改变地图 ,那么在迭代密钥集时使用随机抽样方法 。 实际上,你所做的就是遍历keySet()返回的集合,并在每个项目上计算想要获取该密钥的概率,给定总体需要的数量以及到目前为止所用的数量。 然后生成一个随机数,看看该数字是否低于概率。 (注意:即使您只需要1个密钥, 此方法也将始终有效 ;在这种情况下,它不一定是最有效的方法。)
  • HashMap中的键实际上已经是伪随机顺序。 在极端情况下,您只需要一个给定可能映射的随机密钥 ,您甚至可以拔出keySet()第一个元素
  • 其他情况下 (对于给定的可能地图,您需要多个可能的随机键,或者地图将在您使用随机键之间发生变化),您基本上必须创建或维护从中选择随机的键的数组/列表键。

我真的不知道你为什么要这样做…但如果它有帮助,我创建了一个RandomMap,当你调用values()时会自动随机化这些值,那么下面的可运行的演示应用程序可能会完成这项任务。 。

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

下面是一个如何使用Peter Stuifzand描述的数组方法的示例,也是通过values() -method:

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

通常你并不真正想要一个随机值,而只需要任何值,然后这样做很好:

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

将其转换为数组,然后在热路径中获取该值太慢。

所以得到集合(键或键值集)并执行以下操作:

  public class SetUtility { public static Type getRandomElementFromSet(final Set set, Random random) { final int index = random.nextInt(set.size()); Iterator iterator = set.iterator(); for( int i = 0; i < index-1; i++ ) { iterator.next(); } return iterator.next(); } 

我编写了一个实用程序来从地图,条目集或迭代器中检索随机条目,键或值。

既然你不能也不应该弄清楚迭代器的大小( Guava可以做到这一点 ),你将不得不重载randEntry()方法来接受一个大小,该大小应该是条目的长度。

 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 map = new HashMap() { private static final long serialVersionUID = 1L; { put("Foo", 1); put("Bar", 2); put("Baz", 3); } }; System.out.println(randEntryValue(map)); } static  Entry randEntry(Iterator> it, int count) { int index = (int) (Math.random() * count); while (index > 0 && it.hasNext()) { it.next(); index--; } return it.next(); } static  Entry randEntry(Set> entries) { return randEntry(entries.iterator(), entries.size()); } static  Entry randEntry(Map map) { return randEntry(map.entrySet()); } static  K randEntryKey(Map map) { return randEntry(map).getKey(); } static  V randEntryValue(Map map) { return randEntry(map).getValue(); } } 

这取决于你的密钥是什么 – hashmap的性质不允许这很容易发生。

我能想到的方法是选择一个介于1和hashmap大小之间的随机数,然后开始迭代它,保持计数 – 当count等于你的随机数时你选择,这是你的随机元素。

这是一本来自Objects First with Java的练习。它如下所示.pickDefaultResponse()使用ArrayList生成一个响应并获取一个随机生成的整数并将其用作ArrayList的索引。 这是有效的但我想要克服的是填写两个列表。这里HashMap实例responseMap以及ArrayList实例defaultResponses都必须单独填写。

 import java.util.HashMap; import java.util.HashSet; import java.util.ArrayList; import java.util.Iterator; import java.util.Random; /** * The responder class represents a response generator object. * It is used to generate an automatic response, based on specified input. * Input is presented to the responder as a set of words, and based on those * words the responder will generate a String that represents the response. * * Internally, the reponder uses a HashMap to associate words with response * strings and a list of default responses. If any of the input words is found * in the HashMap, the corresponding response is returned. If none of the input * words is recognized, one of the default responses is randomly chosen. * * @version 1.0 * @author Michael Kolling and David J. Barnes */ public class Responder { // Used to map key words to responses. private HashMap responseMap; // Default responses to use if we don't recognise a word. private ArrayList defaultResponses; private Random randomGenerator; /** * Construct a Responder */ public Responder() { responseMap = new HashMap(); defaultResponses = new ArrayList(); fillResponseMap(); fillDefaultResponses(); randomGenerator = new Random(); } /** * Generate a response from a given set of input words. * * @param words A set of words entered by the user * @return A string that should be displayed as the response */ public String generateResponse(HashSet words) { Iterator it = words.iterator(); while(it.hasNext()) { String word = it.next(); String response = responseMap.get(word); if(response != null) { return response; } } // If we get here, none of the words from the input line was recognized. // In this case we pick one of our default responses (what we say when // we cannot think of anything else to say...) return **pickDefaultResponse();** } /** * Enter all the known keywords and their associated responses * into our response map. */ private void fillResponseMap() { responseMap.put("crash", "Well, it never crashes on our system. It must have something\n" + "to do with your system. Tell me more about your configuration."); responseMap.put("crashes", "Well, it never crashes on our system. It must have something\n" + "to do with your system. Tell me more about your configuration."); responseMap.put("slow", "I think this has to do with your hardware. Upgrading your processor\n" + "should solve all performance problems. Have you got a problem with\n" + "our software?"); responseMap.put("performance", "Performance was quite adequate in all our tests. Are you running\n" + "any other processes in the background?"); responseMap.put("bug", "Well, you know, all software has some bugs. But our software engineers\n" + "are working very hard to fix them. Can you describe the problem a bit\n" + "further?"); responseMap.put("buggy", "Well, you know, all software has some bugs. But our software engineers\n" + "are working very hard to fix them. Can you describe the problem a bit\n" + "further?"); responseMap.put("windows", "This is a known bug to do with the Windows operating system. Please\n" + "report it to Microsoft. There is nothing we can do about this."); responseMap.put("macintosh", "This is a known bug to do with the Mac operating system. Please\n" + "report it to Apple. There is nothing we can do about this."); responseMap.put("expensive", "The cost of our product is quite competitive. Have you looked around\n" + "and really compared our features?"); responseMap.put("installation", "The installation is really quite straight forward. We have tons of\n" + "wizards that do all the work for you. Have you read the installation\n" + "instructions?"); responseMap.put("memory", "If you read the system requirements carefully, you will see that the\n" + "specified memory requirements are 1.5 giga byte. You really should\n" + "upgrade your memory. Anything else you want to know?"); responseMap.put("linux", "We take Linux support very seriously. But there are some problems.\n" + "Most have to do with incompatible glibc versions. Can you be a bit\n" + "more precise?"); responseMap.put("bluej", "Ahhh, BlueJ, yes. We tried to buy out those guys long ago, but\n" + "they simply won't sell... Stubborn people they are. Nothing we can\n" + "do about it, I'm afraid."); } /** * Build up a list of default responses from which we can pick one * if we don't know what else to say. */ private void fillDefaultResponses() { defaultResponses.add("That sounds odd. Could you describe that problem in more detail?"); defaultResponses.add("No other customer has ever complained about this before. \n" + "What is your system configuration?"); defaultResponses.add("That sounds interesting. Tell me more..."); defaultResponses.add("I need a bit more information on that."); defaultResponses.add("Have you checked that you do not have a dll conflict?"); defaultResponses.add("That is explained in the manual. Have you read the manual?"); defaultResponses.add("Your description is a bit wishy-washy. Have you got an expert\n" + "there with you who could describe this more precisely?"); defaultResponses.add("That's not a bug, it's a feature!"); defaultResponses.add("Could you elaborate on that?"); } /** * Randomly select and return one of the default responses. * @return A random default response */ private String **pickDefaultResponse()** { // Pick a random number for the index in the default response list. // The number will be between 0 (inclusive) and the size of the list (exclusive). int index = randomGenerator.nextInt(defaultResponses.size()); return defaultResponses.get(index); } }