2016-02-03 4 views
3

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

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

Ниже приведен код для лаборатории, над которой я работаю. Лаборатория спрашивает, что я завершаю определенные методы в этом файле, так что, когда драйвер компилируется и запускается, соответствующие ответы возвращаются в командную строку. I считаю тем, что я сделал до сих пор, правильно, когда я запускаю драйвер. Но когда я пытаюсь завершить метод 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

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

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

ETA: ДОБАВЛЕНИЕ ответ, который был предоставлен и еще один вопрос, испытываемого при МОЕ FIX

После @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 

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

+0

Ваш sugge Стойка работала.Я обнаружил, что мне пришлось удалить 'numberOfEntries ++; ', поскольку я продолжал получать« NullPointerExceptions ». С некоторым копанием я заметил, что он добавлял «null» в массивы. Как только я удалил это, все прошло правильно. Хорошая работа и отличный совет! – Pwrcdr87

+0

Отличный материал - рад, что все получилось. – gar

1

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

if(!thisBag.isEmpty()){ 

To:

if(thisBag.length>0){ 

И:

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

To:

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