从JAVA+;堆栈溢出错误
我需要找到一种快速有效的方法,在数组项中创建唯一的对(如果有两个以上) 我的第一个问题是,我提出的这段代码有时抛出java.lang.StackOverflowerError,为什么?我知道助手中的递归调用会让它变得更深入,但是如何修复它呢 我的第二个问题是如何使代码更高效。我不需要使用数组-它可以是其他集合类型 这就是我想到的:从JAVA+;堆栈溢出错误,java,arrays,Java,Arrays,我需要找到一种快速有效的方法,在数组项中创建唯一的对(如果有两个以上) 我的第一个问题是,我提出的这段代码有时抛出java.lang.StackOverflowerError,为什么?我知道助手中的递归调用会让它变得更深入,但是如何修复它呢 我的第二个问题是如何使代码更高效。我不需要使用数组-它可以是其他集合类型 这就是我想到的: import java.util.HashMap; import java.util.concurrent.ThreadLocalRandom; /** * Ge
import java.util.HashMap;
import java.util.concurrent.ThreadLocalRandom;
/**
* Generates unique pairs from items in array. Each item cannot occur more than
* once as key nor value.
*
* @author lkallas
*/
public class UniquePairs {
private static final String[] NAMES
= new String[]{"Aaron", "Barney", "Charlie", "Desiré", "Edward"};
private static final HashMap<String, String> PAIRS = new HashMap<>();
public static void main(String[] args) {
// Check if there is more than one item in array.
if (NAMES.length > 1) {
// Find pairs
for (String name : NAMES) {
if (!PAIRS.containsKey(name)) {
PAIRS.put(name, helper(name));
}
}
// Show results.
PAIRS.entrySet().stream().forEach((pair) -> {
System.out.println(pair.getKey() + " - " + pair.getValue());
});
} else {
System.out.println(NAMES[0]);
}
}
/**
* Helper for finding partner.
*
* @param key Name that need partner.
* @return Unique partner.
*/
private static String helper(String key) {
// Get random partner from array.
String partner = NAMES[getRandomInt(0, NAMES.length - 1)];
// Cannot pair up a name with itself. Also partner cannot occur more than once.
if (key.equals(partner) || PAIRS.containsValue(partner)) {
partner = helper(key);
}
return partner;
}
/**
* Random integer in the given range.
*
* @param min Minimum value of the random integer.
* @param max Maximum value of the random integer.
* @return Random integer in given range.
*/
private static int getRandomInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
而不是
return new Random().nextInt((max - min) + 1) + min;
编辑2:
为这种操作创建了特殊类。如有必要,请随意使用
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
/**
*
* @author lkallas
*/
public class MatchMaker {
private final Map<Object, Object> PAIRS;
private List<? extends Object> items;
public MatchMaker() {
this.PAIRS = new HashMap<>();
}
/**
* Pairs items uniquely and randomly so that keys nor values are repeated.
* For proper pairing of Objects it is recommended to provide your own
* implementation of <code>equals()</code> method. Also bear in mind that
* you should also override <code>hashCode()</code> if there's any chance of
* your objects being used in a hash table.
*
* @param input List with objects that are paired with each other.
* @return Map with generated pairs.
* @throws IllegalArgumentException When input List is empty or contains
* only one item.
*/
public Map<?, ?> getPairs(List<? extends Object> input)
throws IllegalArgumentException {
if (input.size() > 1) {
items = input;
for (int i = 0; i < input.size() - 1; i++) {
Object k = input.get(i);
PAIRS.put(k, getPartner(k));
}
Object k = items.get(items.size() - 1);
if (PAIRS.containsValue(k)) {
PAIRS.put(k, getPartner(k));
} else {
Object k1 = items.get(getRandomInt(0, items.size() - 1));
PAIRS.put(k, PAIRS.get(k1));
PAIRS.put(k1, k);
}
} else {
throw new IllegalArgumentException("Can't pair one or less items.");
}
return PAIRS;
}
/**
* Helper for finding a random partner.
*
* @param key Object that needs partner.
* @return Unique partner that is not used by other keys.
*/
private Object getPartner(Object key) {
// Get random partner from array.
Object partner = items.get(getRandomInt(0, items.size() - 1));
// Cannot pair up a key with itself. Also partner cannot occur more than once.
if (key.equals(partner) || PAIRS.containsValue(partner)) {
partner = getPartner(key);
}
return partner;
}
/**
* Random integer in the given range.
*
* @param min Minimum value of the random integer.
* @param max Maximum value of the random integer.
* @return Random integer in given range.
*/
private static int getRandomInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
改变这个
for (String name : NAMES) {
if (!PAIRS.containsKey(name)) {
PAIRS.put(name, helper(name));
}
}
到
for(int i=0;i
您的版本发生了什么,请参见。基本上,在最后一步中,您的选项已经用完,因此
helper
会反复调用自身,直到出现StackOverflowerError
为止。TLDR,但是getRandomInt
是一个错误:您不应该每次都创建一个新的Random
对象。我昨天解释过这一点。你们俩是同一个班还是什么的@保尔·伯丁顿不,我们不是!这甚至不是家庭作业或smth。这只是我想创造的一段代码,让我的生活更轻松。好吧,我的答案解释了会发生什么。如果在最后一步没有选项,helper
将继续调用自身,直到发生stackoverflower错误。如果选项数为零,则需要进行交换。由于java 7,您可以简单地使用ThreadLocalRandom.current().nextInt(min,max)
[max+1,如果您的意思是包含的话](出于某种原因,min/max方法是TLR独有的)没有问题。我很高兴能帮上忙。
for (String name : NAMES) {
if (!PAIRS.containsKey(name)) {
PAIRS.put(name, helper(name));
}
}
for (int i = 0; i < NAMES.length - 1; i++) {
String name = NAMES[i];
PAIRS.put(name, helper(name));
}
String name = NAMES[NAMES.length - 1];
if (PAIRS.containsValue(name)) {
PAIRS.put(name, helper(name));
} else {
String otherKey = NAMES[ThreadLocalRandom.current().nextInt(0, NAMES.length - 1)];
PAIRS.put(name, PAIRS.get(otherKey));
PAIRS.put(otherKey, name);
}