【问题标题】:In an ArrayList of Stacks, why are the indexes incorrect if a Stack(s) are empty?在堆栈的 ArrayList 中,如果堆栈为空,为什么索引不正确?
【发布时间】:2013-03-13 13:22:15
【问题描述】:


我有一个堆栈的 ArrayList,在其中我将一个元素添加到其中一个堆栈并遍历列表,打印每个堆栈的索引。

然后我从上一个 Stack 中删除元素,将其添加到下一个 Stack,打印每个 Stack 的索引,然后对 ArrayList 中的所有 Stack 继续此操作。

但是,当任何堆栈为空时,在获取 ArrayList 中每个堆栈的索引时会出现非常不寻常的行为。 为空的 Stack 将具有正确的索引值,而 为空的 Stack 将具有不正确的索引值指数值。

此外,似乎如果包含元素的堆栈位于索引 0 处,所有其他索引值都将为 1。如果包含元素的堆栈位于任何其他索引处,它将具有正确的索引值和所有其他索引值索引值将为 0。



这是我的代码:
import java.util.List;
import java.util.Stack;
import java.util.ArrayList;

public class ListOfStacks {

    // instance variables:
    List<Stack<Integer>> stacks;
    private static final int NUMBER_OF_STACKS = 3;

    // constructor:
    ListOfStacks() {
        this.stacks = new ArrayList<Stack<Integer>>(NUMBER_OF_STACKS);

        // adding the stacks to the list here:
        for (int i = 0; i < NUMBER_OF_STACKS; i++) {
            this.stacks.add(new Stack<Integer>());
        }
    }

    // instance methods:
    void addElement(int stackIndex, int element) {
        this.stacks.get(stackIndex).add(element);
    }
    void removeElement(int stackIndex) {
        this.stacks.get(stackIndex).pop();
    }
    void printIndexes(int stackIndex, int element) {
        System.out.printf("The stack at index %d now contains %d" +
            "(the other stacks are empty):%n", stackIndex, element);

        for (Stack<Integer> stack : this.stacks) {
            System.out.printf("index %d%n", this.stacks.indexOf(stack));
        }
        System.out.println();
    }

    // main method:
    public static void main(String[] args) {
        ListOfStacks list = new ListOfStacks();
        int index = 0, number = 5;

        // adding the number 5 to the stack at index 0:
        list.addElement(index, number);
        list.printIndexes(index, number);

        // now removing that element, and adding it to the stack at index 1:
        list.removeElement(index++);
        list.addElement(index, number);
        list.printIndexes(index, number);

        // now removing that element, and adding it to the stack at index 2:
        list.removeElement(index++);
        list.addElement(index, number);
        list.printIndexes(index, number);
    }
} // end of ListOfStacks


...这是输出(对于三个堆栈的 ArrayList):

The stack at index 0 now contains 5 (the other stacks are empty):
index 0
index 1
index 1

The stack at index 1 now contains 5 (the other stacks are empty):
index 0
index 1
index 0

The stack at index 2 now contains 5 (the other stacks are empty):
index 0
index 0
index 2


【问题讨论】:

    标签: java arraylist stack indexof


    【解决方案1】:

    您得到错误索引号的原因与 indexOf 在 List 中的实现方式有关。在它下面调用Stack.equals()。这决定了堆栈是否在元素方面是相等的。当您使用空堆栈调用list.indexOf 时,它将返回列表中第一个空堆栈的索引。

    【讨论】:

    • 感谢@DeltaLima 的帮助,那么我该如何使用空堆栈实现“正常”索引行为?
    • 嗯...如果没有更多关于您要达到的目标的知识,这有点难以回答。我想知道List的选择是否正确。不是一个简单的数组在这里工作吗?
    • 感谢@DeltaLima,我之前曾尝试使用堆栈数组,但出现了几个错误(请参阅:stackoverflow.com/questions/15530118/…)。我的目的是创建一个合适的结构来解决河内塔问题。
    • 所以,我发现要像this.stack = new Stack[3]; 那样初始化堆栈数组,会出现警告“Type safety: The expression of type Stack[] needs unchecked conversion to conform to Stack&lt;Integer&gt;[]”。一个可能的解决方案是在构造函数和/或方法上方使用注释@SuppressWarnings("unchecked"),但可能不安全(虽然不知道为什么)。
    【解决方案2】:
    indexOf(Object o) 
              Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
    

    java中的堆栈基本上是一个向量,向量类有这个等于

     /**
      969        * Compares the specified Object with this Vector for equality.  Returns
      970        * true if and only if the specified Object is also a List, both Lists
      971        * have the same size, and all corresponding pairs of elements in the two
      972        * Lists are <em>equal</em>.  (Two elements {@code e1} and
      973        * {@code e2} are <em>equal</em> if {@code (e1==null ? e2==null :
      974        * e1.equals(e2))}.)  In other words, two Lists are defined to be
      975        * equal if they contain the same elements in the same order.
      976        *
      977        * @param o the Object to be compared for equality with this Vector
      978        * @return true if the specified Object is equal to this Vector
      979        */
      980       public synchronized boolean equals(Object o) {
      981           return super.equals(o);
      982       }
    

    所以发生的事情是 indexof 找到第一个空堆栈,将其视为相等并返回该索引。

    所以当索引 0 有元素而其他没有元素时,第一个等于空堆栈的堆栈是位置 1。

    如果另一个元素有数据并且第一个元素相等并且您正在寻找一个空堆栈,它将始终停止并返回索引 0。

    【讨论】:

    • 谢谢@Midpipps,所以我需要覆盖.equals(Object o) 和/或.indexOf(Object o) 来实现“正常”的索引行为吗?
    • 您可以创建一个扩展堆栈类的类,并将 equals 方法重写为引用相等。我不知道这是否是最好的方法,但它应该会给你你正在寻找的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2021-07-20
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 2019-10-06
    • 2012-05-10
    相关资源
    最近更新 更多