比较数组值和HashMap

时间:2015-03-03 19:45:24

标签: java arrays hashmap

我正在制作一个石头剪刀游戏,我应该将用户的最后四个投掷保存到HashMap中。最后四次抛出将在Pattern类中。我有它,所以如果模式已经在HashMap中,那么该值将增加1,表明用户已经重复该模式一次。模式将用于预测用户下一步行动。但是,当我比较两个模式时,HashMap中的那个模式和我刚刚传入的模式,即使它们不相同,它也会返回它们是相同的。我已经尝试了一段时间,但我无法找出问题所在。一些帮助将不胜感激!错误出现在第二个输入。如果我输入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();
  }
}

3 个答案:

答案 0 :(得分:1)

您的HashCode错误。

应该用小写字母书写。

 public int hashCode()

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

答案 1 :(得分:0)

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

第一个问题是它没有被使用(它应该是Pattern#hashCode),第二个问题是它没有计算你的想法。

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

作为旁注,Pattern不是该类名称的绝佳选择,因为它与java.util.regex.Pattern冲突。在这种情况下,这可能是一个问题,因为它可以与Scanner一起使用。

答案 2 :(得分:0)

正如另一个答案所指出的,首先要做的是重命名和注释你的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()方法相等时,它们应该具有相同的哈希码。

在你的情况下会发生的事情是你通过测试所有输入键的相等性来查找HashCode(我会在一分钟内完成它,这是一件坏事),所以equals告诉你你在哈希映射中有相同的键。但哈希映射本身使用hashCode()中的get()方法来定位对象。并且根据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);

这是您如何使用MapHashMap的重点是,您可以在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