Как сделать ссылку на ссылку в Java? - PullRequest
0 голосов
/ 14 января 2019

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

Проблема в том, что я не могу создать другой массив с удаленным элементом и изменить ссылку. Потому что у меня нет реальной ссылки в настроенном классе итераторов. Мне нужно изменить реальную ссылку. Позвольте мне объяснить это лучше в коде:

public class Iterator<E>
{
    private E[] buffer; // underlying buffer.
    private int idx; // location of iterator in buffer.
    private E last_element; // last element returned by this iterator.

    public Iterator(E[] arr)
    {
        buffer = arr;
        idx = 0;

    }

     /**
     * Removes from the underlying collection the last element returned
     * by this iterator.
     */
    public void remove()
    {
        ...
    }


}

Я могу создать копию буфера с удалением указанного элемента и изменить ссылку на буфер на него. Но я хочу, чтобы это удаление действовало на реальный массив. Так что я на самом деле нужно изменить обр [].

Опять же, я знаю, что все это использование массива бессмысленно при наличии иерархии Collection, но мне нужен способ для этого таким образом. Ссылка на ссылку не является хорошей терминологией в этом случае, но у меня была реализация для этого в C ++, и я искал что-то вроде указателя на указатель.

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 14 января 2019

Если вам нужен «указатель указателя», я вижу два пути: первый - создать массив только с одним элементом, или второй - создать собственный класс-оболочку, содержащую этот элемент.

Я приведу пример первого способа:

public class Iterator<E>
{
    private E[][] pointerToPointer;
    private E[] buffer; // underlying buffer.
    private int idx; // location of iterator in buffer.
    private E last_element; // last element returned by this iterator.

    public Iterator(E[][] pointerToPointer)
    {   
        this.pointerToPointer = pointerToPointer;
        buffer = pointerToPointer[0];
        idx = 0;

    }

     /**
     * Removes from the underlying collection the last element returned
     * by this iterator.
     */
    public void remove()
    {
        // create your new array (let's call it newArr)
        ...

        buffer = newArr;
        pointerToPointer[0] = buffer;
    }
}

Затем, когда вы вызываете свой итератор, вы должны создать массив singleton:

Integer[] arr = ...
Integer[][] pointerToPointer = {arr};
Iterator<Integer> it = new Iterator<>(new Integer[][]{pointerToPointer});

//use your iterator, including remove() method
...

arr = pointerToPointer[0]; //this gets the modified array

В любом случае, что мешает вам добавить метод к вашему классу Iterator, который возвращает поле buffer?

0 голосов
/ 15 января 2019

Java является передачей по значению, а не передачей по ссылке, что означает; Вы копируете данные и позволяете сборщику мусора позаботиться обо всем остальном. Таким образом, у вас нет указателей, которые есть в C ++.

Это моя идея, имеющая один плохой побочный эффект - массив фиксируется и выделяется массиву, анализируемому конструктору (индекс удаляется, но заменяется на ноль):

public void remove(int index) {
        @SuppressWarnings("unchecked")
        E[] tmp = (E[])new Object[this.buffer.length]; // Can cause issues on some types
        int x = 0; // Variable to track tmp's index counter
        for(int i = 0; i < this.buffer.length; i++) {
            if(i != index) {                
                x++;
                tmp[x] = this.buffer[i]; 
            }

        }
        this.buffer = tmp;
    }
0 голосов
/ 14 января 2019

Это уже так в вашем примере ...

Установка buffer на arr, позволяет создать копию ссылки на тот же массив в куче, содержащий одинаковые ссылки всех элементов.

НО факт, что вы не должны использовать массив таким образом, если вы хотите удалить элемент.

Вы просто должны использовать список элементов того же типа.

Измените вашу реализацию, чтобы использовать List<E> вместо массивов, и вы сможете вызывать метод remove для него, влияя на исходный переданный экземпляр списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...