比较数组值和 HashMap
Comparing Array Values and HashMap
我正在制作剪刀石头布游戏,我应该将用户的最后四次投掷保存到 HashMap 中。最后四次投掷将在模式 class 内。我有它,如果该模式已经在 HashMap 中,则该值将增加 1,表明用户已重复该模式一次。这些模式将用于预测用户的下一步行动。但是,当我比较两个模式时,HashMap 中的模式和我刚刚传入的模式,即使它们不相同,但 returns 它们是相同的。我已经尝试对此进行了一段时间的调查,但找不到问题所在。一些帮助将不胜感激!错误出现在第二个输入处。如果我输入 R,它会将它保存在 HashMap 中,但是当我输入任何其他内容时,它会抛出 NullPointerException,我认为这是因为新模式未存储在 hashmap 中,但我试图获取它的值,因为程序认为它等于 HashMap 中已有的那个。我认为问题出在 Pattern 中的 equals() 内部,但我不完全确定。
import java.util.*;
public class RockPaperScisors{
public static void main(String[] args){
Scanner key = new Scanner(System.in);
Pattern pattern = new Pattern();
Pattern pattern1;
Computer comp = new Computer();
boolean stop = false;
int full=0;;
while ( !stop ){
System.out.println("Enter R P S. Enter Q to quit.");
char a = key.next().charAt(0);
if ( a == 'Q' ){
stop = true;
break;
}
pattern.newPattern(a);
char[] patt = pattern.getPattern();
for ( int i = 0; i < patt.length; i++ ){
System.out.print(patt[i] + " ");
}
pattern1 = new Pattern(patt);
comp.storePattern(pattern1);
System.out.println();
System.out.println("Patterns: " + comp.getSize());
full++;
}
}
}
import java.util.*;
public class Pattern{
private char[] pattern;
private int full = 0;
public Pattern(){
pattern = new char[4];
}
public Pattern(char[] patt){
pattern = patt;
}
public char[] getPattern(){
return pattern;
}
public void newPattern(char p){
if ( full <= 3 ){
pattern[full] = p;
full ++;
}
else{
for (int i = 0; i <= pattern.length-2; i++) {
pattern[i] = pattern[i+1];
}
pattern[pattern.length-1] = p;
}
}
public int HashCode(){
char[] a = pattern;
return a.hashCode();
}
public boolean equals( Object o ) {
if( o == this ) { return true; }
if(!(o instanceof Pattern)){ return false; }
Pattern s = (Pattern) o;
if (Arrays.equals(s.getPattern(), pattern))
System.out.println("Yes");
return Arrays.equals(s.getPattern(), pattern);
}
}
import java.util.*;
import java.util.Map.Entry;
public class Computer{
private HashMap<Pattern, Integer> map;
public Computer(){
map = new HashMap <Pattern, Integer>();
}
public void storePattern(Pattern p){
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
}
else
map.put(p, 0);
}
public int getSize(){
return map.size();
}
}
你的哈希码是错误的。
应该写成小写
public int hashCode()
为了确保方法被覆盖,使用@Override注解。
Pattern#HashCode
中的问题完全有可能。
第一个问题是它没有被使用(应该是Pattern#hashCode
),第二个问题是它没有计算你认为的那样
您可能会发现 java.util.Arrays#hashCode
非常有用,将支持从数组更改为 List
也可以。
附带说明一下,Pattern
不是 class 名称的好选择,因为它与 java.util.regex.Pattern
冲突。在这种情况下,这比在其他情况下可能更成问题,因为它可以与 Scanner
一起使用。
正如另一个答案所指出的,要做的第一件事是重命名并注释您的 hashcode() 方法。
然后,你也必须修复它。它使用
char[] a = pattern;
return a.hashCode();
这意味着它使用了 char[]
对象的 hashCode()
函数。但该函数直接继承自 Object
,并为两个相等的字符数组提供不同的哈希码。例如,试试这个:
char[] c = { 'a','b','c' };
char[] d = { 'a','b','c' };
System.out.printf("%d %d%n", c.hashCode(), d.hashCode());
你会看到它打印了两个不同的数字。
所以你需要使用更好的哈希码函数。您可以自己制作或使用 Arrays.hashCode(pattern)
(不需要本地 a
变量)。重要的是,当两个Patterns根据equals()
方法相等时,它们应该具有相同的哈希码。
在您的情况下,您通过测试所有输入键的相等性来查找 HashCode(我稍后会讲到,这是一件坏事),所以 equals
告诉你你在哈希映射中有相同的键。但是hash map本身是使用get()
中的hashCode()
方法来定位对象的。并且根据hashCode()
方法,hash map中没有对象具有相同的key!
因此,当对象相等时,它们必须始终一致。
现在,至于你查找对象的方法:
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
} else
map.put(p, 0);
这不是您使用Map
的方式。 HashMap
的全部意义在于,您可以在 O(1) 中查看它是否包含某个键。你正在做的是迭代它并比较 - 那是 O(N),非常浪费。
如果你正确地实现了你的 hashCode()
,你可以通过执行 map.containsKey(p)
而不是那个循环来查找它。如果你确定你没有在地图中放置空值,你可以简单地使用 get()
来获取你的模式:
Integer time = map.get(p);
if ( time == null ) {
map.put( p, 0 );
} else {
map.put( p, time+1);
}
(你不需要使用++
,因为你把它放入地图后实际上并没有使用time
)。
我正在制作剪刀石头布游戏,我应该将用户的最后四次投掷保存到 HashMap 中。最后四次投掷将在模式 class 内。我有它,如果该模式已经在 HashMap 中,则该值将增加 1,表明用户已重复该模式一次。这些模式将用于预测用户的下一步行动。但是,当我比较两个模式时,HashMap 中的模式和我刚刚传入的模式,即使它们不相同,但 returns 它们是相同的。我已经尝试对此进行了一段时间的调查,但找不到问题所在。一些帮助将不胜感激!错误出现在第二个输入处。如果我输入 R,它会将它保存在 HashMap 中,但是当我输入任何其他内容时,它会抛出 NullPointerException,我认为这是因为新模式未存储在 hashmap 中,但我试图获取它的值,因为程序认为它等于 HashMap 中已有的那个。我认为问题出在 Pattern 中的 equals() 内部,但我不完全确定。
import java.util.*;
public class RockPaperScisors{
public static void main(String[] args){
Scanner key = new Scanner(System.in);
Pattern pattern = new Pattern();
Pattern pattern1;
Computer comp = new Computer();
boolean stop = false;
int full=0;;
while ( !stop ){
System.out.println("Enter R P S. Enter Q to quit.");
char a = key.next().charAt(0);
if ( a == 'Q' ){
stop = true;
break;
}
pattern.newPattern(a);
char[] patt = pattern.getPattern();
for ( int i = 0; i < patt.length; i++ ){
System.out.print(patt[i] + " ");
}
pattern1 = new Pattern(patt);
comp.storePattern(pattern1);
System.out.println();
System.out.println("Patterns: " + comp.getSize());
full++;
}
}
}
import java.util.*;
public class Pattern{
private char[] pattern;
private int full = 0;
public Pattern(){
pattern = new char[4];
}
public Pattern(char[] patt){
pattern = patt;
}
public char[] getPattern(){
return pattern;
}
public void newPattern(char p){
if ( full <= 3 ){
pattern[full] = p;
full ++;
}
else{
for (int i = 0; i <= pattern.length-2; i++) {
pattern[i] = pattern[i+1];
}
pattern[pattern.length-1] = p;
}
}
public int HashCode(){
char[] a = pattern;
return a.hashCode();
}
public boolean equals( Object o ) {
if( o == this ) { return true; }
if(!(o instanceof Pattern)){ return false; }
Pattern s = (Pattern) o;
if (Arrays.equals(s.getPattern(), pattern))
System.out.println("Yes");
return Arrays.equals(s.getPattern(), pattern);
}
}
import java.util.*;
import java.util.Map.Entry;
public class Computer{
private HashMap<Pattern, Integer> map;
public Computer(){
map = new HashMap <Pattern, Integer>();
}
public void storePattern(Pattern p){
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
}
else
map.put(p, 0);
}
public int getSize(){
return map.size();
}
}
你的哈希码是错误的。
应该写成小写
public int hashCode()
为了确保方法被覆盖,使用@Override注解。
Pattern#HashCode
中的问题完全有可能。
第一个问题是它没有被使用(应该是Pattern#hashCode
),第二个问题是它没有计算你认为的那样
您可能会发现 java.util.Arrays#hashCode
非常有用,将支持从数组更改为 List
也可以。
附带说明一下,Pattern
不是 class 名称的好选择,因为它与 java.util.regex.Pattern
冲突。在这种情况下,这比在其他情况下可能更成问题,因为它可以与 Scanner
一起使用。
正如另一个答案所指出的,要做的第一件事是重命名并注释您的 hashcode() 方法。
然后,你也必须修复它。它使用
char[] a = pattern;
return a.hashCode();
这意味着它使用了 char[]
对象的 hashCode()
函数。但该函数直接继承自 Object
,并为两个相等的字符数组提供不同的哈希码。例如,试试这个:
char[] c = { 'a','b','c' };
char[] d = { 'a','b','c' };
System.out.printf("%d %d%n", c.hashCode(), d.hashCode());
你会看到它打印了两个不同的数字。
所以你需要使用更好的哈希码函数。您可以自己制作或使用 Arrays.hashCode(pattern)
(不需要本地 a
变量)。重要的是,当两个Patterns根据equals()
方法相等时,它们应该具有相同的哈希码。
在您的情况下,您通过测试所有输入键的相等性来查找 HashCode(我稍后会讲到,这是一件坏事),所以 equals
告诉你你在哈希映射中有相同的键。但是hash map本身是使用get()
中的hashCode()
方法来定位对象的。并且根据hashCode()
方法,hash map中没有对象具有相同的key!
因此,当对象相等时,它们必须始终一致。
现在,至于你查找对象的方法:
boolean contains = false;
for (Entry<Pattern, Integer> entry : map.entrySet())
{
Pattern patt = entry.getKey();
if ( p.equals(patt) ){
contains = true;
}
}
if ( contains ){
int time = map.get(p);
time++;
map.put(p, time);
} else
map.put(p, 0);
这不是您使用Map
的方式。 HashMap
的全部意义在于,您可以在 O(1) 中查看它是否包含某个键。你正在做的是迭代它并比较 - 那是 O(N),非常浪费。
如果你正确地实现了你的 hashCode()
,你可以通过执行 map.containsKey(p)
而不是那个循环来查找它。如果你确定你没有在地图中放置空值,你可以简单地使用 get()
来获取你的模式:
Integer time = map.get(p);
if ( time == null ) {
map.put( p, 0 );
} else {
map.put( p, time+1);
}
(你不需要使用++
,因为你把它放入地图后实际上并没有使用time
)。