繁体   English   中英

比较数组值和HashMap

[英]Comparing Array Values and HashMap

我当时正在制作剪刀石头布的游戏,应该将用户的最后四步保存到HashMap中。 最后四次抛出将在Pattern类中。 我拥有它,以便如果该模式已经在HashMap中,则该值将增加1,表明用户已重复该模式一次。 这些模式将用于预测用户的下一步行动。 但是,当我比较两种模式时,即使HashMap中的一种和我刚刚传入的一种,即使它们不相同,它也会返回它们是相同的。 我已经尝试研究了一段时间,但是我找不到问题所在。 一些帮助将不胜感激! 错误在第二个输入处出现。 如果我输入R,它将保存在HashMap中,但是当我输入其他任何内容时,它将抛出NullPointerException,我认为是因为新模式未存储在哈希图中,但是由于程序认为,我试图获取它的值它等于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();
  }
}

您的HashCode错误。

应该用小写形式。

 public int hashCode()

为了确保该方法被覆盖,请使用@Override批注。

Pattern#HashCode中的问题完全有可能。

第一个问题是它没有被使用(应该是Pattern#hashCode ),第二个问题是它没有计算出您认为的含义。

您可能会发现java.util.Arrays#hashCode非常有用,将数组的支持从数组更改为List也将起作用。

附带说明一下, Pattern不是该类名称的理想选择,因为它与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变量)。 重要的是,当两个模式根据equals()方法equals() ,它们应该具有相同的哈希码。

在这种情况下,您会通过测试所有输入键的相等性来查找HashCode(我将在一分钟内完成,这是一件坏事),所以equals告诉您您在输入键中具有相同的键哈希图。 但是哈希图本身使用get()hashCode()方法来定位对象。 根据hashCode()方法,哈希图中没有具有相同键的对象!

因此,当对象相等时,它们必须始终保持一致。


现在,至于您查找对象的方法:

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 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM