Java中的堆栈,有问题;包括「;

Java中的堆栈,有问题;包括「;,java,stack,contains,Java,Stack,Contains,我在程序中使用堆栈,但当程序试图检查堆栈中包含的元素时,我遇到了一个问题。我在堆栈中使用整数数组。简单的例子是: Stack<int[]> myStack = new Stack<int[]>(); myStack.push(new int[]{1,2}); myStack.push(new int[]{1,3}); myStack.push(new int[]{1,4}); if (mySt

我在程序中使用堆栈,但当程序试图检查堆栈中包含的元素时,我遇到了一个问题。我在堆栈中使用整数数组。简单的例子是:

        Stack<int[]> myStack = new Stack<int[]>();
        myStack.push(new int[]{1,2});
        myStack.push(new int[]{1,3});
        myStack.push(new int[]{1,4});
        if (myStack.contains(new int[]{1,3})) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }

这很简单:
int[]
通过身份进行比较

new int[]{1,3}.equals(new int[]{1,3})
返回false。有许多解决方案:

  • 使用
    列表
    。这效率很低,但可能已经足够了
  • int[]
    包装到一个对象中,并实现
    equals
    hashCode
  • 使用像trove4j这样的基本集合库,它提供类似于
    List
要打印“是”,需要将堆栈设置为某个对象,该对象定义了
equals()
hashCode()
,这样具有相同元素的两个数组将被视为相等

所以类似这样的事情(这只是一闪而过,可能会更好):


然后让你的
Stack
be
Stack

contains()方法依赖于equals()的结果-如果你想要完全控制,子类和over-ride equals()就意味着你想要的

class ArrayWrapper {
    int[] data;

    public boolean equals(Object o) {
        if (o instanceof ArrayWrapper)
            return Arrays.equals(data, ((ArrayWrapper) o).data);
        return false;
    }

    public int hashCode() {
        return Arrays.hashCode(data);
    }
}
另一个修复方法是覆盖
包含的
,如中所示

class SmartStack extends Stack<int[]> {
    @Override
    public boolean contains(Object o) {
        ...
    }
}
类SmartStack扩展堆栈{
@凌驾
公共布尔包含(对象o){
...
}
}

首先,您必须定义“包含”的含义。Stack.com的文档包含以下内容:

返回:true当且仅当指定对象与此向量中的组件相同时(由equals方法确定)

(堆栈扩展向量)


因此,您可以创建自己的类,其中包含一个int数组作为实例变量,并覆盖该类上的“equals”,以实现在您的情况下的含义。只要确保你做得正确。有关如何做到这一点的信息是

int[]数组对象无法知道两个数组是否相等,因为它们实际上只是指针,并且由于它们指向两个不同的数组,因此被认为是不相等的。指针用于比较相等的原因是因为对象类以这种方式定义了最基本的相等方法

您需要创建一个简单的类来封装数组。 这里有一个大家都能理解的简单例子

class IntArray {
    int[] myArray;
    public IntArray () {
        myArray = new int[0];
    }
    public IntArray (int [] array) {
        myArray = array;
    }
    /**
     * This method is for accessing the array.
     * The array CAN be modified using this method.
     */
    public int[] getArray() {
        return myArray;
    }
    /**
     * Uses built-in hashCode generating method
     * within the Arrays class.
     * Importing java.util.Arrays is necessary.
     */
    public int hashCode() {
        return Arrays.hashCode(myArray);
    }
    public boolean equals(Object o) {
        if (!(o instanceof IntArray))
            return false;

        //Should use Arrays.equals(o.myArray, myArray);

        if (o.myArray.length != myArray.length)
            return false;
        else {
            for (int i = 0; i < myArray.length; i++) {
                if (myArray[i] != o.myArray[i]) {
                    return false;
                }
            }
            return true;
        }
    }
}
class IntArray{
int[]myArray;
公共IntArray(){
myArray=newint[0];
}
公共数组(int[]数组){
myArray=数组;
}
/**
*此方法用于访问阵列。
*可以使用此方法修改数组。
*/
public int[]getArray(){
返回myArray;
}
/**
*使用内置的哈希代码生成方法
*在Arrays类中。
*导入java.util.array是必要的。
*/
公共int hashCode(){
返回array.hashCode(myArray);
}
公共布尔等于(对象o){
如果(!(o IntArray实例))
返回false;
//应该使用array.equals(o.myArray,myArray);
if(o.myArray.length!=myArray.length)
返回false;
否则{
for(int i=0;i
完成此操作后,您可以轻松地执行与以前类似的操作:

    Stack<In> myStack = new Stack<int[]>();
    myStack.push( new IntArray (new int[]{1,2}) );
    myStack.push( new IntArray (new int[]{1,3}) );
    myStack.push( new IntArray (new int[]{1,4}) );
    if (myStack.contains( new IntArray (new int[]{1,3})) ) {
        System.out.println("YES");
    } else {
        System.out.println("NO");
    }
Stack myStack=new Stack();
push(newintarray(newint[]{1,2}));
push(newintarray(newint[]{1,3}));
push(newintarray(newint[]{1,4}));
if(myStack.contains(newintarray(newint[]{1,3}))){
System.out.println(“是”);
}否则{
系统输出打印项次(“否”);
}

这肯定会起作用。

+1-但您可能应该警告某人对包装的
int[]
进行变异的陷阱。此外,OP的示例实际上可能是“对象拒绝”的情况,他可能真正需要的是一个特定于域的类,而不是对这两个注释使用通用包装的
int[]
+1。如果他真的需要一个包装的
int[]
,他应该使用。类
堆栈
(就像
向量
哈希表
)只是很久以前的遗留问题,不应该再使用IMHO了。不幸的是,集合框架的现代部分没有堆栈,但是您可以通过对ArrayList进行子类化并实现两个简单的方法来创建一个堆栈。您确定,没有更多的方法需要重写吗?不,如果我们想确保Stack的所有方法都安全工作,我们需要重写近十几个方法。因此,无可否认,这不是一个很好的解决方案。但它确实避免了包装器对象或动态列表的开销。如果我在一个堆栈中有许多数组,并且不关心代码的“白痴证明”,我可能会这样做。
class IntArray {
    int[] myArray;
    public IntArray () {
        myArray = new int[0];
    }
    public IntArray (int [] array) {
        myArray = array;
    }
    /**
     * This method is for accessing the array.
     * The array CAN be modified using this method.
     */
    public int[] getArray() {
        return myArray;
    }
    /**
     * Uses built-in hashCode generating method
     * within the Arrays class.
     * Importing java.util.Arrays is necessary.
     */
    public int hashCode() {
        return Arrays.hashCode(myArray);
    }
    public boolean equals(Object o) {
        if (!(o instanceof IntArray))
            return false;

        //Should use Arrays.equals(o.myArray, myArray);

        if (o.myArray.length != myArray.length)
            return false;
        else {
            for (int i = 0; i < myArray.length; i++) {
                if (myArray[i] != o.myArray[i]) {
                    return false;
                }
            }
            return true;
        }
    }
}
    Stack<In> myStack = new Stack<int[]>();
    myStack.push( new IntArray (new int[]{1,2}) );
    myStack.push( new IntArray (new int[]{1,3}) );
    myStack.push( new IntArray (new int[]{1,4}) );
    if (myStack.contains( new IntArray (new int[]{1,3})) ) {
        System.out.println("YES");
    } else {
        System.out.println("NO");
    }