Дублирование всех объектов в ArrayBag

В настоящее время я изучаю различные DataStructures в Java, одна из которых - Array Bags и Linked Bags. Я понимаю причину, по которой структуры данных так важны, и то, как дженерики позволяют нам легче обрабатывать объекты единообразным образом, независимо от их типа (если мое мышление или понимание этого утверждения неверно по причине использования структур данных, скажи пожалуйста).

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

Ниже приведен код лаборатории, над которой я работаю. Лаборатория просит, чтобы я выполнил определенные методы в этом файле, чтобы при компиляции и запуске драйвера соответствующие ответы возвращались в командную строку. Я считаю, что то, что я сделал до сих пор, правильно, когда я запускаю драйвер. Но когда я пытаюсь завершить duplicateAll() метод (от второго до последнего метода в файле ниже), я продолжаю сталкиваться с одной и той же ошибкой (ями) независимо от того, как я пытаюсь ее изменить. Пожалуйста, имейте в виду, что мой последний метод removeDuplicates() не завершена, но я еще не в той части лаборатории.

Вот код:

import java.util.Arrays;
import java.util.Random;

public final class ArrayBag<T> implements BagInterface<T> {

    private final T[] bag;
    private int numberOfEntries;
    private static final int DEFAULT_CAPACITY = 25;

    private boolean initialized = false;
    private static final int MAX_CAPACITY = 10000;

    /** Creates an empty bag whose initial capacity is 25. */
    public ArrayBag() {
        this(DEFAULT_CAPACITY);
    } // end default constructor

    /**
     * Creates an empty bag having a given initial capacity.
     *
     * @param desiredCapacity The integer capacity desired.
     */
    public ArrayBag(int desiredCapacity) {
        if (desiredCapacity <= MAX_CAPACITY) {

            // The cast is safe because the new array contains null entries.
            @SuppressWarnings("unchecked")
            T[] tempBag = (T[]) new Object[desiredCapacity]; // Unchecked cast
            bag = tempBag;
            numberOfEntries = 0;
            initialized = true;
        }
        else
            throw new IllegalStateException("Attempt to create a bag " +
                                            "whose capacity exceeds " +
                                            "allowed maximum.");
    } // end constructor

    /** Adds a new entry to this bag.
    @param newEntry The object to be added as a new entry.
    @return True if the addition is successful, or false if not. */
    public boolean add(T newEntry) {
        checkInitialization();
        boolean result = true;
        if (isArrayFull()) {
            result = false;
        } else { // Assertion: result is true here
            bag[numberOfEntries] = newEntry;
            numberOfEntries++;
        } // end if
        return result;

    } // end add

    /** Throws an exception if this object is not initialized.
     * 
     */
    private void checkInitialization()
    {
        if (!initialized)
             throw new SecurityException("ArrayBag object is not initialized " +
                                        "properly.");
    }

    /** Retrieves all entries that are in this bag.
    @return A newly allocated array of all the entries in the bag. */
    public T[] toArray() {

        // the cast is safe because the new array contains null entries
        @SuppressWarnings("unchecked")
        T[] result = (T[]) new Object[numberOfEntries]; // unchecked cast
        for (int index = 0; index < numberOfEntries; index++) {
            result[index] = bag[index];
        } // end for
        return result;
    } // end toArray

    /** Sees whether this bag is full.
    @return True if the bag is full, or false if not. */
    private boolean isArrayFull() {
        return numberOfEntries >= bag.length;
    } // end isArrayFull

    /** Sees whether this bag is empty.
    @return True if the bag is empty, or false if not. */
    public boolean isEmpty() {
        return numberOfEntries == 0;
    } // end isEmpty

    /** Gets the current number of entries in this bag.
    @return The integer number of entries currently in the bag. */
    public int getCurrentSize() {
        return numberOfEntries;
    } // end getCurrentSize

    /** Counts the number of times a given entry appears in this bag.
    @param anEntry The entry to be counted.
    @return The number of times anEntry appears in the bag. */
    public int getFrequencyOf(T anEntry) {
        checkInitialization();
        int counter = 0;
        for (int index = 0; index < numberOfEntries; index++) {
            if (anEntry.equals(bag[index])) {
                counter++;
            } // end if
        } // end for
        return counter;
    } // end getFrequencyOf

    /** Tests whether this bag contains a given entry.
    @param anEntry The entry to locate.
    @return True if the bag contains anEntry, or false if not. */
    public boolean contains(T anEntry) {
        checkInitialization();
        return getIndexOf(anEntry) > -1;
    } // end contains

    /** Removes all entries from this bag. */
    public void clear() {
        while (!isEmpty()) {
            remove();
        }
    } // end clear

    /** Removes one unspecified entry from this bag, if possible.
    @return Either the removed entry, if the removal was successful,
    or null if otherwise. */
    public T remove() {
        checkInitialization();

        // MODIFY THIS METHOD TO REMOVE A RANDOM ITEM FROM THE BAG
        Random randomNum = new Random();
        if(numberOfEntries > 0){
        int randomKey = randomNum.nextInt(numberOfEntries);
        T result = removeEntry(randomKey);
        return result;
        }else{
            return null;
        }
    } // end remove

    /** Removes one occurrence of a given entry from this bag.
    @param anEntry The entry to be removed.
    @return True if the removal was successful, or false if not. */
    public boolean remove(T anEntry) {
        checkInitialization();
        int index = getIndexOf(anEntry);
        T result = removeEntry(index);
        return anEntry.equals(result);
    } // end remove

    // Removes and returns the entry at a given array index within the array bag.
    // If no such entry exists, returns null.
    // Preconditions: 0 <= givenIndex < numberOfEntries;
    //                  checkInitialization has been called.
    private T removeEntry(int givenIndex) {
        T result = null;
        if (!isEmpty() && (givenIndex >= 0)) {
            result = bag[givenIndex];                   // entry to remove
            bag[givenIndex] = bag[numberOfEntries - 1]; // Replace entry with last entry
            bag[numberOfEntries - 1] = null;            // remove last entry
           numberOfEntries--;
         } // end if
        return result;
    } // end removeEntry

    // Locates a given entry within the array bag.
    // Returns the index of the entry, if located, or -1 otherwise.
    // Precondition: checkInitialization has been called.
    private int getIndexOf(T anEntry) {
        int where = -1;
        boolean stillLooking = true;
        int index = 0;
        while ( stillLooking && (index < numberOfEntries)) {
            if (anEntry.equals(bag[index])) {
                stillLooking = false;
                where = index;
            } // end if
            index++;
        } // end for
    // Assertion: If where > -1, anEntry is in the array bag, and it
    // equals bag[where]; otherwise, anEntry is not in the array
        return where;
    } // end getIndexOf


    /** Override the equals method so that we can tell if two bags contain the same items
     * the contents in the bag.
     * @return a string representation of the contents of the bag */
    public String toString() {

        String result = "Bag{Size:" + numberOfEntries + " ";


        for (int index = 0; index < numberOfEntries; index++) {
            result += "[" + bag[index] + "] ";
        } // end for

        result += "}";
        return result;
    } // end toArray

    /*********************************************************************
     * 
     * METHODS TO BE COMPLETED
     * 
     * 
         ************************************************************************/

    /** Check to see if two bags are equals.  
     * @param aBag Another object to check this bag against.
     * @return True the two bags contain the same objects with the same frequencies.
     */
    public boolean equals(ArrayBag<T> aBag) {
        boolean result = false; // result of comparison of bags
        boolean sameLength = false;

        T[] thisBag = this.toArray();
        T[] otherBag = aBag.toArray();

        Arrays.sort(thisBag);
        Arrays.sort(otherBag);

        if (thisBag.length == otherBag.length){
            sameLength = true;
        }

        if(sameLength){
            for(int index = 0; index < otherBag.length; index++)
            {
                if(thisBag[index].equals(otherBag[index])){
                    result = true;
                }
            }
        }

        return result;
    }  // end equals

    /** Duplicate all the items in a bag.
     * @return True if the duplication is possible.
     */
    public boolean duplicateAll() {
        checkInitialization();
        boolean success = false;
        T[] thisBag = this.toArray();
        if(!thisBag.isEmpty()){
            int originalTotalEntries = numberOfEntries;
            for(int index = 0; index < originalTotalEntries; index++){
                success = thisBag.add(thisBag[index]);
                numberOfEntries++;
            }
        }
        return success;
    }  // end duplicateAll

        /** Remove all duplicate items from a bag
     */
    public void removeDuplicates() {
        checkInitialization();

        // COMPLETE THIS METHOD 

        return;
    }  // end removeDuplicates

} // end ArrayBag

Когда я пытаюсь скомпилировать код, я получаю следующие ошибки:

./ArrayBag.java:260: error: cannot find symbol
      if(!thisBag.isEmpty()){
                 ^
symbol:   method isEmpty()
location: variable thisBag of type T[]
where T is a type-variable:
T extends Object declared in class ArrayBag
./ArrayBag.java:263: error: cannot find symbol
            success = thisBag.add(thisBag[index]);
                             ^
symbol:   method add(T)
location: variable thisBag of type T[]
where T is a type-variable:
T extends Object declared in class ArrayBag
2 errors

я пробовал this. на месте thisBag как следующее (только вставка duplicateAll() метод:

public boolean duplicateAll() {
    checkInitialization();
    boolean success = false;
    T[] thisBag = this.toArray();  //not needed anymore
    if(!this.isEmpty()){
        int originalTotalEntries = this.numberOfEntries;
        for(int index = 0; index < originalTotalEntries; index++){
            success = this.add(this[index]);
            numberOfEntries++;
        }
    }
    return success;
}  // end duplicateAll   

И я получаю следующую ошибку во время компиляции:

./ArrayBag.java:263: error: array required, but ArrayBag<T> found
            success = this.add(this[index]);
                                   ^
where T is a type-variable:
T extends Object declared in class ArrayBag
1 error

Итак, я знаю, что так как я не бросил this правильно, я получаю ошибку прямо выше. Но две ошибки, опубликованные выше последней, - это то, где я зацикливаюсь.

Мои вопросы:

Почему я получаю эти ошибки? Я получил похожие ошибки, касающиеся cannot find symbol в моем последнем классе Java, и это было, когда я считаю, что я не был должным образом создан? Я думал, что мой подход был правильным, потому что я бросил T[] thisBag = this.toArray();, а затем попытался использовать thisBag и записи в коде в методе. Так как это неправильно, я не уверен, как очистить их generics и ArrayBag/Bag DataStructures.

Кроме того, я подхожу к дублированию записей в общей сумке или есть лучший способ, о котором я не знаю? Я пытаюсь использовать add() метод в этом файле в моих интересах, но у меня, очевидно, возникают трудности. Просматривая документацию по API Java в Интернете, я вижу, что для достижения этого дублирования можно воспользоваться несколькими путями:

arrays.fill

arrays.setAll(T[] array, IntFunction<? extends T> generator)

arrays.clone

Я думаю, что сначала мне нужно убедиться, что в массиве достаточно фиксированного пространства, чтобы дублировать его в памяти. Если нет, мне пришлось бы использовать динамический массив, удвоить пространство и дважды скопировать содержимое в новый массив. Это ново для меня и лично не вникал в этот тип подхода (только что изучил концепцию).

Как всегда, я с нетерпением жду возможности услышать, как вы все решите подобную проблему! А также скажите мне, что я делаю не так!

ЭТА: ДОБАВЛЕНИЕ ОТВЕТА, КОТОРЫЙ БЫЛ ПРЕДОСТАВЛЕН, И ДРУГОЙ ВОПРОС, ОПЫТНЫЙ С МОЕЙ ИСПРАВЛЕНИЕ

После того, как @gar предложил ниже, я реализовал следующее:

public boolean duplicateAll() {
    checkInitialization();
    boolean success = false;
    T[] thisBag = this.toArray();  //not needed anymore
    if(!this.isEmpty()){
        int originalTotalEntries = this.numberOfEntries;
        for(int index = 0; index < originalTotalEntries; index++){
            success = this.add(thisBag[index]);
            numberOfEntries++;
        }
    }
    return success;
}  // end duplicateAll

Когда я сделал это, я начал получать следующую ошибку:

    Exception in thread "main" java.lang.NullPointerException
    at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:325)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
    at java.util.Arrays.sort(Arrays.java:1246)
    at ArrayBag.equals(ArrayBag.java:234)
    at BagExtensionsTest.checkDuplicateAll(BagExtensionsTest.java:720)
    at BagExtensionsTest.main(BagExtensionsTest.java:52)

Я покопался на этом сайте и прочитал, что это вызвано null записи в массивах (отсюда java.lang.NullPointerException, Добавили некоторые System.out.println строки, чтобы увидеть изменения размеров моих массивов при их дублировании и заметили, что первый массив (который содержал одну запись) заканчивался тремя записями. Я удалил numberOfEntries++; с конца duplicateAll() метод, и это исправило мою проблему.

Просто подумал, что я поделюсь этой информацией, чтобы другие знали.

Как всегда, отличная информация!

2 ответа

Решение

Вы путаетесь между методами вашего объекта и массива. Вы, кажется, довольно близко со второй попытки, которую вы предоставили. isEmpty метод на вашем ArrayBag класс в то время как [...] аксессор только для массивов. Изменение фрагмента кода, чтобы получить запись для добавления из массива вместо объекта, будет выглядеть так:

public boolean duplicateAll() {
    checkInitialization();
    boolean success = false;
    T[] thisBag = this.toArray();  //not needed anymore
    if(!this.isEmpty()){
        int originalTotalEntries = this.numberOfEntries;
        for(int index = 0; index < originalTotalEntries; index++){
            success = this.add(thisBag[index]);
            numberOfEntries++;
        }
    }
    return success;
}  // end duplicateAll

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

Попробуйте заменить это:

    if(!thisBag.isEmpty()){

Для того, чтобы:

    if(thisBag.length>0){

А также:

    success = this.add(this[index]);

Для того, чтобы:

   success = this.add(thisBag[index]);
Другие вопросы по тегам