Стек в Java, проблема с "содержит" - PullRequest
3 голосов
/ 20 апреля 2011

Я использую стек в моей программе, но у меня проблема, когда программа пытается проверить, какой элемент содержится в стеке.Я использую массив целых чисел в стеке.Краткий пример:

        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[] myInteger = new int[]{1,3};
myStack.push(myInteger);
myStack.contains(myInteger);

Ответы [ 6 ]

6 голосов
/ 20 апреля 2011

Это просто: int[] сравнивать по тождеству,

new int[]{1,3}.equals(new int[]{1,3})

возвращает false.Есть много решений:

  • Используйте взамен List<Integer>.Это довольно неэффективно, но может быть достаточно.
  • Оберните int[] в объект и внедрите equals и hashCode.
  • Используйте примитивную коллекционную библиотеку, такую ​​как trove4j, которая предоставляет вещи, подобныеList<int>
1 голос
/ 20 апреля 2011

Объекты массива int [] не могут узнать, равны ли два массива, поскольку они в действительности являются просто указателями, а поскольку они указывают на два разных массива, они считаются неравными. Причина, по которой указатели используются для сравнения равенства, заключается в том, что класс Object определяет самый элементарный метод равенства таким способом.

Вам нужно создать простой класс для инкапсуляции вашего массива. Вот простой, понятный любому.

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");
    }

Это определенно должно сработать.

1 голос
/ 20 апреля 2011

Одним из вариантов является использование оболочки, например

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);
    }
}

Другим исправлением будет переопределение contains, как в

class SmartStack extends Stack<int[]> {
    @Override
    public boolean contains(Object o) {
        ...
    }
}
1 голос
/ 20 апреля 2011

Чтобы заставить его печатать «ДА», вам нужно сделать из стека некоторый объект, который определил equals() и hashCode(), чтобы два массива с одинаковыми элементами считались равными.

Так что-то вроде этого (которое только что накатано и, возможно, могло бы быть лучше):

public class ArrayHolder
{
    private int[] theArray;

    public ArrayHolder(int[] theArray) {
       this.theArray = theArray;
    }

    public array() {
        return theArray;
    }

    public boolean equals(Object o) {
        // Code that will return true if
        // o is an int[] that contains the
        // same elements as this
    }

    public int hashCode() {
        // code that will return a hash
        // based on the array elements so
        // that arrays with the same elements
        // will have the same hash
    }
}

А потом пусть ваш Stack будет Stack<ArrayHolder>.

0 голосов
/ 20 апреля 2011

Сначала вы должны определить, что означает «содержит». Документы для Stack.contains говорят:

Возвращает: true, если и только если указанный объект совпадает с компонентом в этом векторе, как определено методом equals.

(Стек расширяет Вектор)

Таким образом, вы можете создать свой собственный класс с массивом целых чисел в качестве переменной экземпляра и переопределить «равно» для этого класса, чтобы реализовать то, что когда-либо это означает в вашем случае. Просто убедитесь, что вы делаете это правильно. Информация о том, как это сделать, везде

0 голосов
/ 20 апреля 2011

Метод contains () опирается на результат equals () - если вы хотите, чтобы полный контроль, подкласс и over-ride equals () означали то, что вы намерены.

...