我正在尝试在my previous post中描述的多个二维数组中找到类似的行。对于下面给出的示例,答案为false, true,
,尽管它应为false, false
。
另一个非常重要的问题是如何将此代码调整为具有不同行数的数组。
我非常感谢任何帮助。感谢。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
ArrayList<Integer[]> array1 = new ArrayList<Integer[]>();
ArrayList<Integer[]> array2 = new ArrayList<Integer[]>();
ArrayList<Integer[]> array3 = new ArrayList<Integer[]>();
array1.add(new Integer[]{1,2,3}); array1.add(new Integer[]{1,0,3});
array2.add(new Integer[]{1,0,3}); array2.add(new Integer[]{0,0,3});
array3.add(new Integer[]{1,2,3}); array3.add(new Integer[]{0,3,3});
for (int i=0; i<array1.size(); i++) {
boolean answ = equalRows(array1.get(i),array2.get(i),array3.get(i));
System.out.println(answ);
}
}
static class Row extends Object {
private int value;
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 () {
return this.value;
}
}
private static Map<Row, Integer> map(Integer[] row) {
Map<Row, Integer> rowMap = new HashMap<Row, Integer>();
for (int i=0; i<row.length; i++)
rowMap.put(new Row(row[i]), i);
return rowMap;
}
private static boolean equalRows(Integer[] row1, Integer[] row2, Integer[] row3){
Map<Row, Integer> map1 = map(row1);
Map<Row, Integer> map2 = map(row2);
for (int i=0; i<row3.length; i++){
Row row = new Row(row3[i]);
Integer result1 = map1.get(row);
Integer result2 = map2.get(row);
if (result1 == null || result2 == null) {
return false;
}
}
return true;
}
}
修改#1 在第一次测试中,我比较{1,2,3},{1,0,3}和{1,2,3}。在第二个:{1,0,3},{0,0,3},{0,3,3}。第二行的问题是{0,0,3}和{0,3,3}被解决为{0,3}。我不知道如何修改代码以在{0,0,3}和{0,3,3}之间进行区分(我仍然应该使用HashMap)。
修改#2 我的想法是首先从array1和array2中取出行,然后将它们放入映射中。然后我从array3中取一行并尝试在地图中找到它。如果我无法在任何这些地图中找到它,那么这意味着行不相似。
答案 0 :(得分:1)
我不太确定你想要完成什么,但可能是你的问题在于方法
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);
}
因为
if(this == obj)
例如,您希望进行值比较 - 但是使用“==”编译器得到的是两个对象引用的比较?
所以也许
if(this.equals(obj))
是你想要的吗?
此外,您是否尝试在每个语句的调试模式语句中单步执行代码?我猜想这样可以快速找到你的错...
欢呼:)答案 1 :(得分:1)
要比较两个数组,忽略空值
public static <T> boolean equalsExceptForNulls(T[] ts1, T[] ts2) {
if (ts1.length != ts2.length) return false;
for(int i = 0; i < ts1.length; i++) {
T t1 = ts1[i], t2 = ts2[i];
if (t1 != null && t2 != null && !t1.equals(t2))
return false;
}
return true;
}
public static <T> boolean equalsExceptForNulls3(T[] ts1, T[] ts2, T[] ts3) {
return equalsExceptForNulls(ts1, ts2) &&
equalsExceptForNulls(ts1, ts3) &&
equalsExceptForNulls(ts2, ts3);
}
// or generically
public static <T> boolean equalsExceptForNulls(T[]... tss) {
for(int i = 0; i < tss.length - 1; i++)
for(int j = i + 1; i < tss.length; j++)
if(!equalsExceptForNulls(tss[i], tss[j])
return false;
return true;
}
你遇到的问题是array3用于确定要比较的行。
在第一个测试中,您要比较行1,2,3和第二个测试,比较第0行和第3行。第一个测试应为false,第二个测试应为true。
我通过在调试器中单步执行代码找到了问题。我建议你这样做。
我还会使用int[]
代替Integer[]
答案 2 :(得分:1)
您的方法存在一个基本问题,导致此错误。您正在使用地图来确定元素在其他行中的位置。在构造地图时,如果行中存在重复的元素,则它们的先前索引将被覆盖。这正是您的案例中发生的事情。第二个数组的第二行有一个重复的零。
这是第二行地图的样子
map1 = ((Row(1), 0), (Row(0), 1), (Row(3), 3))
map2 = ((Row(0), 1), (Row(3), 3))
Nnotice map2 bcoz中只有两个元素,第一个元素被第二个元素覆盖。当您使用第三个数组中第二行的元素进行查找时,查找总是成功(因为它只查找0和3,从不查看1)
此外,您检查失败的条件是不完整的,即
if (result1 == null || result2 == null) {
return false;
}
应该是
if (result1 == null || result2 == null || !result1.equals(i) || !result2.equals(i)) {
return false;
}
在我看来,你根本不应该使用地图。而是逐个比较每个元素。要概括不同长度的数组的代码,请尝试使用ArrayList类的size()方法。
如果你应该使用一个地图很重要,那么你应该使用每个数组元素的索引作为键,使用Row对象作为值,而不是反过来。