在复合对象的 HashMap 中找不到键

发布于 2024-11-03 09:32:25 字数 9391 浏览 2 评论 0原文

因此,我在 Java 中使用 3 个成员创建了自己的复合键

public class MyOwnKey{
int location;
int length;
String [] tokens;
}

现在我使用构造函数创建了两个对象

String [] tokens = "Stackoverflow is great".split("\\s+");
Object key1 = new MyOwnKey(0,0,tokens)
tokens = "Web is great".split("\\s+");
Object key2 = new MyOwnKey(0,0,tokens)

现在,我将键添加到 HashMap 中 HashMap 映射 = new HashMap(); 映射.put(key1,1);

现在,这就是问题所在 当我包含 key 时,它给出 false;

**map.containsKey(key2) //returns false whereas it should return true.**

这样才有意义:

key1.equals(key2) returns true

并且 hashcode 代码也是相等的。 key1.hashCode() == key2.hashCode()。

我已经实现了我自己版本的 hashCode、toEquals() 和 toCompare()。

不确定是什么问题。

这是代码

import java.io.DataOutput;
import java.io.DataInput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

public class PatternGeneratorKey implements WritableComparable<Object> {


    private String [] tokens;
    int location;
    int length;

    StringBuffer _toString = null;

    public PatternGeneratorKey(){
        tokens = new String[1];
        location =0;
        length=1;
    }

    public PatternGeneratorKey(int location, int length, String [] tokens){

        this.location = location;
        this.length = length;

        this.tokens=  new String[tokens.length];
        for(int i = 0; i < tokens.length;i++){
            this.tokens[i] = tokens[i];
        }

    }

    public int compareTo(Object o) {
        if (!(o instanceof PatternGeneratorKey))
            return -1;
        return this.compareTo((PatternGeneratorKey) o);
    }

    public void write(DataOutput out) throws IOException {

        out.writeInt(tokens.length);
        for(int i = 0; i<tokens.length;i++){
            out.writeUTF(tokens[i]);

        }
        out.writeInt(location);
        out.writeInt(length);
    }

    public void readFields(DataInput in) throws IOException {

        int l = in.readInt();

        tokens = new String[l];
        for(int i = 0; i < l ; i++){
            tokens[i] = in.readUTF();
        }
        location = in.readInt();
        length = in.readInt();
    }

    public int compareTo(PatternGeneratorKey k) {

        if(this.tokens.length - this.length != k.tokens.length - k.length){
            return this.tokens.length - this.length -( k.tokens.length - k.length);
        }

        if(this.location != k.location){
            return this.location  - k.location;
        }

        int i = 0 , j= 0;
        for(i = 0, j=0 ; i < this.tokens.length && j < k.tokens.length;){

            if(i == this.location ){
                i = i + length;
                continue;
            }
            if( j == k.location){
                j = j + k.length;
                continue;
            }
            if(!this.tokens[i].equalsIgnoreCase(k.tokens[j])){
                return this.tokens[i].compareTo(k.tokens[j]);
            }else{
                i++;
                j++;
            }
        }


        //TODO: add comparison on left out phrase
        return 0;
    }

    public int hashCode() {
        int hashCode=0;     
        for(int i = 0; i < tokens.length;){

            if(i == location ){

                i = i + length;
                continue;
            }
            hashCode += tokens[i++].hashCode();
        }

        hashCode+= location + tokens.length;
        return hashCode;
    }


    public String toString(){

        if(_toString == null){
            _toString = new StringBuffer();
            for(int k = 0; k < tokens.length ;k++){
                if(k==location){
                    _toString.append(":").append(" ");
                    k=k+length-1;
                }else{
                    _toString.append(tokens[k]).append(" ");
                }
            }
        }

        return _toString.toString();
    }

    public boolean equals(PatternGeneratorKey k) {

        if(this.tokens.length - this.length == k.tokens.length - k.length 
                && this.location == k.location){

            //assume second one is larger
            String tokens[] = k.tokens;
            int length = k.length;
            int location = k.location;

            String [] tokens1 = this.tokens;
            int length1 = this.length;
            int location1 = this.location;
            //make the local variable point to the largest of the two
            if( this.tokens.length > k.tokens.length){
                tokens = this.tokens;
                length = this.length;
                location = this.location;
                tokens1 = k.tokens;
                length1 = k.length;
                location1 = k.location;

            }

            int i = 0 , j= 0;
            for(i = 0, j=0 ; i < tokens.length;){

                if(i == location ){

                    i = i + length;
                    continue;
                }
//              if( j >= location1 && j<= location1 + length1 -1){
                if( j == location1){
                    j = j + length1;
                    continue;
                }
                if(!tokens[i++].equalsIgnoreCase(tokens1[j++])){
                    return false;
                }
            }
            return true;
        }else{
            return false;
        }
    }
}

这是我正在测试的代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.io.Text;


public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String value = "gm used cars";
        // Compile all the words using regex
        String[] tokens = value.toString().split("\\s+");

        //to find pattern we need atleast two words in the query
        if(tokens.length <=1){
            return;
        }

        Map<PatternGeneratorKey,List> map = new HashMap<PatternGeneratorKey, List>();

        for(int l = 1 ; l < tokens.length; l++){
            for(int i = 0 ; i < tokens.length - (l-1); i++){
                String hit = new String(getPhrase(l, i, tokens));
                PatternGeneratorKey key1 = new PatternGeneratorKey(i, l, tokens);
                List list = null;
                for(int k = 0;k< tokens.length;k++){
                    System.out.println("i:" + i + ",l:" + l + ",tokens:" + tokens[k]);
                }
                System.out.println("hashcode:" + key1.hashCode());

                if(!map.containsKey(key1)){
                    list = new ArrayList<String>();
                    map.put(key1, list);
                }else{
                    list = (List) map.get(key1);
                }
                list.add(hit);
            }
        }
            value = "ford used cars";
            String[] tokens2= value.toString().split("\\s+");

            PatternGeneratorKey key2 = new PatternGeneratorKey(0, 1, tokens);

            //run a sliding window for length 1 to tokens length -1
            for(int l = 1 ; l < tokens2.length; l++){
                //genereate token pairs with sliding window. 
                for(int i = 0 ; i < tokens2.length - (l-1); i++){
                    //hit a single token or a + b if there are two.
                    String hit = new String(getPhrase(l, i, tokens2));
                    PatternGeneratorKey key1 = new PatternGeneratorKey(i, l, tokens2);

                    System.out.println();

                    System.out.println(key1.toString() + "|" + key2.toString() + "|"+ key1.equals(key2));
                    for(int k = 0;k< tokens2.length;k++){
                        System.out.println("i:" + i + ",l:" + l + ",tokens:" + tokens2[k]);
                    }
                    System.out.println("hashcode:" + key1.hashCode());

                    List list = null;
                    if(!map.containsKey(key1)){
                        list = new ArrayList<String>();
                        map.put(key1, list);
                    }else{
                        list = (List) map.get(key1);
                    }
                    list.add(hit);
                }
            }

            value = "ford used cars";
            tokens= value.toString().split("\\s+");


            PatternGeneratorKey key1 = new PatternGeneratorKey(0,1,tokens);


             tokens2 = "gm used cars".split("\\s+");
             key2 = new PatternGeneratorKey(0,1,tokens2);

            System.out.println(key1.equals(key2));
            System.out.println(key2.equals(key1));

            System.out.println(key1.hashCode() );
            System.out.println(key2.hashCode() );

            System.out.println(map);

    }

    private static String getPhrase(int l, int i, String[] tokens){

        StringBuffer strin = new StringBuffer();

        int index = 0;
        for(index = i ; index < i+l;index++){
            if(index < i+l-1){
                strin.append(tokens[index]).append("+");
            }
            else
            {
                strin.append(tokens[index]);

            }
        }
        return strin.toString();
    }


}

So, I made my own composite key in Java with 3 members

public class MyOwnKey{
int location;
int length;
String [] tokens;
}

Now I create two objects using the constructor

String [] tokens = "Stackoverflow is great".split("\\s+");
Object key1 = new MyOwnKey(0,0,tokens)
tokens = "Web is great".split("\\s+");
Object key2 = new MyOwnKey(0,0,tokens)

Now, I add the key in HashMap
HashMap map = new HashMap();
map.put(key1,1);

Now, this is the problem
when I do contains key, it gives false;

**map.containsKey(key2) //returns false whereas it should return true.**

Just so that it makes sense:

key1.equals(key2) returns true

and the hashcode codes are also equal. key1.hashCode() == key2.hashCode().

I have implemeneted my own version of hashCode, toEquals() and toCompare().

Not sure what's the problem.

Here is the code

import java.io.DataOutput;
import java.io.DataInput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

public class PatternGeneratorKey implements WritableComparable<Object> {


    private String [] tokens;
    int location;
    int length;

    StringBuffer _toString = null;

    public PatternGeneratorKey(){
        tokens = new String[1];
        location =0;
        length=1;
    }

    public PatternGeneratorKey(int location, int length, String [] tokens){

        this.location = location;
        this.length = length;

        this.tokens=  new String[tokens.length];
        for(int i = 0; i < tokens.length;i++){
            this.tokens[i] = tokens[i];
        }

    }

    public int compareTo(Object o) {
        if (!(o instanceof PatternGeneratorKey))
            return -1;
        return this.compareTo((PatternGeneratorKey) o);
    }

    public void write(DataOutput out) throws IOException {

        out.writeInt(tokens.length);
        for(int i = 0; i<tokens.length;i++){
            out.writeUTF(tokens[i]);

        }
        out.writeInt(location);
        out.writeInt(length);
    }

    public void readFields(DataInput in) throws IOException {

        int l = in.readInt();

        tokens = new String[l];
        for(int i = 0; i < l ; i++){
            tokens[i] = in.readUTF();
        }
        location = in.readInt();
        length = in.readInt();
    }

    public int compareTo(PatternGeneratorKey k) {

        if(this.tokens.length - this.length != k.tokens.length - k.length){
            return this.tokens.length - this.length -( k.tokens.length - k.length);
        }

        if(this.location != k.location){
            return this.location  - k.location;
        }

        int i = 0 , j= 0;
        for(i = 0, j=0 ; i < this.tokens.length && j < k.tokens.length;){

            if(i == this.location ){
                i = i + length;
                continue;
            }
            if( j == k.location){
                j = j + k.length;
                continue;
            }
            if(!this.tokens[i].equalsIgnoreCase(k.tokens[j])){
                return this.tokens[i].compareTo(k.tokens[j]);
            }else{
                i++;
                j++;
            }
        }


        //TODO: add comparison on left out phrase
        return 0;
    }

    public int hashCode() {
        int hashCode=0;     
        for(int i = 0; i < tokens.length;){

            if(i == location ){

                i = i + length;
                continue;
            }
            hashCode += tokens[i++].hashCode();
        }

        hashCode+= location + tokens.length;
        return hashCode;
    }


    public String toString(){

        if(_toString == null){
            _toString = new StringBuffer();
            for(int k = 0; k < tokens.length ;k++){
                if(k==location){
                    _toString.append(":").append(" ");
                    k=k+length-1;
                }else{
                    _toString.append(tokens[k]).append(" ");
                }
            }
        }

        return _toString.toString();
    }

    public boolean equals(PatternGeneratorKey k) {

        if(this.tokens.length - this.length == k.tokens.length - k.length 
                && this.location == k.location){

            //assume second one is larger
            String tokens[] = k.tokens;
            int length = k.length;
            int location = k.location;

            String [] tokens1 = this.tokens;
            int length1 = this.length;
            int location1 = this.location;
            //make the local variable point to the largest of the two
            if( this.tokens.length > k.tokens.length){
                tokens = this.tokens;
                length = this.length;
                location = this.location;
                tokens1 = k.tokens;
                length1 = k.length;
                location1 = k.location;

            }

            int i = 0 , j= 0;
            for(i = 0, j=0 ; i < tokens.length;){

                if(i == location ){

                    i = i + length;
                    continue;
                }
//              if( j >= location1 && j<= location1 + length1 -1){
                if( j == location1){
                    j = j + length1;
                    continue;
                }
                if(!tokens[i++].equalsIgnoreCase(tokens1[j++])){
                    return false;
                }
            }
            return true;
        }else{
            return false;
        }
    }
}

And, this is the code I am testing on

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.io.Text;


public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String value = "gm used cars";
        // Compile all the words using regex
        String[] tokens = value.toString().split("\\s+");

        //to find pattern we need atleast two words in the query
        if(tokens.length <=1){
            return;
        }

        Map<PatternGeneratorKey,List> map = new HashMap<PatternGeneratorKey, List>();

        for(int l = 1 ; l < tokens.length; l++){
            for(int i = 0 ; i < tokens.length - (l-1); i++){
                String hit = new String(getPhrase(l, i, tokens));
                PatternGeneratorKey key1 = new PatternGeneratorKey(i, l, tokens);
                List list = null;
                for(int k = 0;k< tokens.length;k++){
                    System.out.println("i:" + i + ",l:" + l + ",tokens:" + tokens[k]);
                }
                System.out.println("hashcode:" + key1.hashCode());

                if(!map.containsKey(key1)){
                    list = new ArrayList<String>();
                    map.put(key1, list);
                }else{
                    list = (List) map.get(key1);
                }
                list.add(hit);
            }
        }
            value = "ford used cars";
            String[] tokens2= value.toString().split("\\s+");

            PatternGeneratorKey key2 = new PatternGeneratorKey(0, 1, tokens);

            //run a sliding window for length 1 to tokens length -1
            for(int l = 1 ; l < tokens2.length; l++){
                //genereate token pairs with sliding window. 
                for(int i = 0 ; i < tokens2.length - (l-1); i++){
                    //hit a single token or a + b if there are two.
                    String hit = new String(getPhrase(l, i, tokens2));
                    PatternGeneratorKey key1 = new PatternGeneratorKey(i, l, tokens2);

                    System.out.println();

                    System.out.println(key1.toString() + "|" + key2.toString() + "|"+ key1.equals(key2));
                    for(int k = 0;k< tokens2.length;k++){
                        System.out.println("i:" + i + ",l:" + l + ",tokens:" + tokens2[k]);
                    }
                    System.out.println("hashcode:" + key1.hashCode());

                    List list = null;
                    if(!map.containsKey(key1)){
                        list = new ArrayList<String>();
                        map.put(key1, list);
                    }else{
                        list = (List) map.get(key1);
                    }
                    list.add(hit);
                }
            }

            value = "ford used cars";
            tokens= value.toString().split("\\s+");


            PatternGeneratorKey key1 = new PatternGeneratorKey(0,1,tokens);


             tokens2 = "gm used cars".split("\\s+");
             key2 = new PatternGeneratorKey(0,1,tokens2);

            System.out.println(key1.equals(key2));
            System.out.println(key2.equals(key1));

            System.out.println(key1.hashCode() );
            System.out.println(key2.hashCode() );

            System.out.println(map);

    }

    private static String getPhrase(int l, int i, String[] tokens){

        StringBuffer strin = new StringBuffer();

        int index = 0;
        for(index = i ; index < i+l;index++){
            if(index < i+l-1){
                strin.append(tokens[index]).append("+");
            }
            else
            {
                strin.append(tokens[index]);

            }
        }
        return strin.toString();
    }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

も星光 2024-11-10 09:32:25

您的问题是由于 equals(PatternGeneratorKey) 没有覆盖 equals(Object) (但它重载了 equals(Object),这样,当 key1key2PatternGeneratorKey 类型的变量时,key1.equals(key2) 返回 true!)。

由于 HashMap 调用 equals(Object) 来检查键是否相等,因此您的方法永远不会被调用,因此您需要实现 equals(Object)

Your problem is caused by the fact that equals(PatternGeneratorKey) doesn't override equals(Object) (but it overloads equals(Object), so that key1.equals(key2) returns true when key1 and key2 are variables of type PatternGeneratorKey!).

Since HashMap calls equals(Object) to check keys for equality, your method never gets called, so you need to implement equals(Object) instead.

嗼ふ静 2024-11-10 09:32:25

hashCode() 或 equals() 中存在错误。向我们展示代码。

疯狂猜测:在您的代码中 key1.equals(key2) 并不意味着 key2.equals(key1) 。

You have a bug in either hashCode() or equals(). Show us the code.

Wild guess: in your code key1.equals(key2) doesn't mean key2.equals(key1).

白馒头 2024-11-10 09:32:25

您为 equals(MyOwnKey) 创建了重载,而不是覆盖 equals(Object)

equals()hashCode() 上使用 @Override 注释。它会在编译时捕获这个相当常见的错误。

You created an overload for equals(MyOwnKey) instead of overriding equals(Object).

Use the @Override annotation on equals() and hashCode(). It will catch this fairly common error at compile time.

没有心的人 2024-11-10 09:32:25

HashMap#containsKey 覆盖 AbstractMap#containsKey - 因此条件的方式存在细微差别:

“当且仅当此映射包含键 k 的映射时返回 true,使得 (key==null ? k==null : key .equals(k))”

已实现。

对于不重写 containsKey() 的 AbstractMap 子类,那么您很可能只需正确实现 equals() 就可以摆脱困境。但是,对于 HashMap,您需要正确实现 hashCode() 并满足适当的标识。

无论如何 - 向我们展示代码。

HashMap#containsKey overrides AbstractMap#containsKey - so there's a subtle difference in the way that the condition:

"Returns true if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k))"

is implemented.

For a subclass of AbstractMap which doesn't override containsKey() then you may well be able to get away with just implementing equals() correctly. However, for a HashMap, you need to have the implementation of hashCode() correct and satisfying the appropriate identity as well.

In any case - show us the code.

瑾兮 2024-11-10 09:32:25

你还没有真正实现 equals 。

public boolean equals(PatternGeneratorKey k) {

不是 HashMap 使用的。它正在寻找 public boolean equals(Object obj) {}

You haven't actually implemented equals.

public boolean equals(PatternGeneratorKey k) {

is not what HashMap uses. It's looking for public boolean equals(Object obj) {}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文