Code for searching similar entires in multiple two

2019-09-09 12:04发布

问题:

I´m trying to write the code for the problem described in my previous topic. The suggested solution was to use hashmaps to find similar entries in multiple arrays (arrays have the same number of columns, but they might have different number of rows).

Below is my sample code based on a code snippet of the user John B provided here. For simplicity and for debugging purpose, I created just 3 different one-dimensional rows instead of two-dimensional arrays. Also, for simplicity, the function equalRows should return true or false instead of row indexes.

So, in the below code the function equalRows should return false, because array3 has {1,3,4} and it does have {1,2,3}. Instead the function returns true. Why does it happen?

import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        int[] array1 = {1,2,3}; 
        int[] array2 = {1,2,3}; 
        int[] array3 = {1,3,4};
        boolean answ = equalRows(array1,array2,array3);
        System.out.println(answ);
    }

    static class Row extends Object {
        private int value;
        private volatile int hashCode = 0;

        public Row(int val) {
            this.value = val;
        }

        @Override
        public boolean equals(Object obj) {
            if(this == obj)
                return true;
            if((obj == null) || (obj.getClass() != this.getClass()))
                return false;
            // object must be Row at this point
            Row row = (Row)obj;
                return (value == row.value);
        }

        @Override
        public int hashCode () {
            final int multiplier = 7;
            if (hashCode == 0) {
                int code = 31;
                code = multiplier * code + value;
                hashCode = code;
            }
            return hashCode;
        }
    }

    private static Map<Row, Integer> map(int[] array) {
          Map<Row, Integer> arrayMap = new HashMap<Row, Integer>();
          for (int i=0; i<array.length; i++)
                arrayMap.put(new Row(array[i]), i);
          return arrayMap;
    }

    private static boolean equalRows(int[] array1, int[] array2, int[] array3){
           Map<Row, Integer> map1 = map(array1);
           Map<Row, Integer> map2 = map(array2);

           for (int i=0; i<array3.length; i++){
              Row row = new Row(array3[i]);
              Integer array1Row = map1.get(row);
              Integer array2Row = map2.get(row);
              if (array1Row != null || array2Row != null) {
                  return false;
              }
           }
        return true;
    }

}

Edit#1 Code is updated subject to suggested solution.

Edit#2 I checked out the suggested solution, but the function returns false even for: int[] array1 = {1,2,3}; int[] array2 = {1,2,3}; int[] array3 = {1,2,3}, although it should be true. I think the problem is with the function hashcode. So, any solution?

回答1:

This line is wrong, it immediately returns true:

if (array1Row != null && array2Row != null) {
    return true;
}

What you must do is this (completely invert the logic):

if (array1Row == null || array2Row == null) {
    return false;
}


回答2:

It is only getting as far as testing the first element in each array and returning true because they match.

You need to return false if any fail to match and then return true if there are no failures.

I'd also put a test of the lengths at the start of the equalRows method.