如何从对象数组中删除元素?

时间:2013-11-21 02:45:10

标签: java arrays

人。现在,我有一个对象数组,我是通过阅读文本文件分配的,我需要一个方法来搜索与该对象匹配的字符串,如果找到,会减少数组的容量并删除该数据元件。该方法是Provider类中的deletePhone()方法,但我似乎无法弄清楚我做错了什么。第一个类仅用于读取文件。

public static void main(String[] args) throws IOException {
      String fileNameIn = args[0];
      Provider provObj = new Provider();
      provObj.readCellPhoneFile(fileNameIn);

      System.out.println(provObj.summary());
      System.out.println(provObj.rates());
      System.out.println(provObj.listByNumber());
      System.out.println(provObj.listByBill());
      System.out.println(provObj.excludedRecordsList());
   }
}

这是我遇到问题的主要课程。这只是我无法弄清楚的deletePhone()方法。

import java.util.Scanner;
import java.io.File;
import java.util.Arrays;
import java.io.IOException;
import java.text.DecimalFormat;

public class Provider {
   private String name;
   private CellPhone[] phones;
   private String[] excludedRecords;

   /**
    * Constructor for Provider class.
    */
   public Provider() {
      name = "not yet assigned";
      phones = new CellPhone[0];
      excludedRecords = new String[0];
   }

   /**
    * Reads in file name and assigns data.
    *
    * @param fileNameIn Input for file name from main
    * @throws IOException from scanning file name
    */
   public void readCellPhoneFile(String fileNameIn) throws IOException {
      //Reads in file name and creates Scanner object
      File fileIn = new File(fileNameIn);
      Scanner scanFile = new Scanner(fileIn);
      //Assigns name from first line
      name = scanFile.nextLine();
      //Assigns data from file to different categories
      while (scanFile.hasNextLine()) {
         Scanner scanPhone = new Scanner(scanFile.nextLine());
         scanPhone.useDelimiter(", *");

         String phoneType = scanPhone.next();
         char phoneChar = phoneType.toUpperCase().charAt(0);
         //Assigns phone to different category
         switch (phoneChar) {   
            case 'F':
               String number = scanPhone.next();
               int texts = Integer.parseInt(scanPhone.next());
               int minutes = Integer.parseInt(scanPhone.next());
               FlipPhone flip1 = new FlipPhone(number, texts, minutes);
               addPhone(flip1);
               break;
            case 'S':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               int data = Integer.parseInt(scanPhone.next());
               SmartPhone smart1 = new SmartPhone(number, texts, minutes, data);
               addPhone(smart1);
               break;
            case 'I':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               data = Integer.parseInt(scanPhone.next());
               int iMessages = Integer.parseInt(scanPhone.next());
               IPhone iPhone1 = new IPhone(number, texts,
                  minutes, data, iMessages);
               addPhone(iPhone1);
               break;
            case 'A':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               data = Integer.parseInt(scanPhone.next());
               int hotspotMin = Integer.parseInt(scanPhone.next());
               Android android1 = new Android(number, texts,
                  minutes, data, hotspotMin);
               addPhone(android1);
               break;
            default:
               String unrecognized = scanPhone.nextLine();
               unrecognized = phoneType + unrecognized; 
               addExcludedRecord(unrecognized);   
         }
      }   
   }

   /**
    * Returns string for provider name.
    *
    * @return String
    */
   public String getName() {
      return name;
   }

   /**
    * Assigns a name input as provider name.
    *
    * @param nameIn Input for provider name
    */
   public void setName(String nameIn) {
      name = nameIn;
   }

   /**
    * Returns CellPhone array for phones.
    *
    * @return CellPhone[]
    */
   public CellPhone[] getPhones() {
      return phones;
   }

   /**
    * Returns string array for excluded records.
    *
    * @return String[]
    */
   public String[] getExcludedRecords() {
      return excludedRecords;
   }

   /**
    * Adds phone to array of phones.
    *
    * @param newPhoneIn Input for phone object
    */
   public void addPhone(CellPhone newPhoneIn) {
      //Increases size of phones array
      CellPhone[] newPhones = new CellPhone[phones.length + 1];
      for (int i = 0; i < phones.length; i++) {
         newPhones[i] = phones[i];
      }
      phones = newPhones;
      //Adds CellPhone object to phones array
      phones[phones.length - 1] = newPhoneIn;
   }

   /**
    * Determines if phone number is found and deleted.
    *
    * @return boolean
    * @param numberIn Input for phone number
    */
   public boolean deletePhone(String numberIn) {
      boolean delete = false;
      int deleteIndex = -1;
      //Searches for phone number match
      for (int i = 0; i < phones.length; i++) {
         if (numberIn.equals(phones[i].getNumber())) {
            deleteIndex = i;
         }
      }
      if (deleteIndex > -1) {
         for (int i = deleteIndex; i < phones.length - 1; i++) {
            phones[i] = phones[i + 1];
            phones[phones.length - 1] = null;
            CellPhone[] newPhones = new CellPhone[phones.length - 1];
            phones = newPhones;
         }
         return true;
      }
      else {
         return false;
      }
   }

   /**
    * Adds unrecognized phone to excluded records.
    *
    * @param excRecIn Input for unrecognized phone
    */
   public void addExcludedRecord(String excRecIn) {
      //Increases capacity of excludedRecords
      String[] newExcRecords = new String[excludedRecords.length + 1];
      for (int i = 0; i < excludedRecords.length; i++) {
         newExcRecords[i] = excludedRecords[i];
      }
      excludedRecords = newExcRecords;
      //Adds excRecIn to array
      excludedRecords[excludedRecords.length - 1] = excRecIn;
   }

   /**
    * Returns list of cell phones in phones array.
    *
    * @return String
    */
   public String toString() {
      String result = "";
      for (CellPhone phone : phones) {
         result += phone + "\n";
      }
      return result;
   }

   /**
    * Calculates total bill for all phones.
    *
    * @return double
    */
   public double calculateTotalBill() {
      double totalBill = 0;
      for (int i = 0; i < phones.length; i++) {
         totalBill += phones[i].calculateBill();
      }   
      return totalBill;
   }

   /**
    * Calculates total number of texts for all phones.
    *
    * @return int
    */
   public int calculateTotalTexts() {
      int totalTexts = 0;
      for (int i = 0; i < phones.length; i++) {
         totalTexts += phones[i].getTexts();
      }   
      return totalTexts;
   }

   /**
    * Calculates total number of minutes for all phones.
    *
    * @return int
    */
   public int calculateTotalMinutes() {
      int totalMinutes = 0;
      for (int i = 0; i < phones.length; i++) {
         totalMinutes += phones[i].getMinutes();
      }   
      return totalMinutes;
   }

   /**
    * Calculates total data for smartphones.
    *
    * @return int
    */
   public int calculateTotalData() {
      int totalData = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof SmartPhone) {
            totalData += ((SmartPhone) phones[i]).getData();
         }   
      }   
      return totalData;
   }

   /**
    * Calculates total hotspot minutes for Androids.
    *
    * @return int
    */
   public int calculateTotalHotspotMin() {
      int totalHotspotMin = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof Android) {
            totalHotspotMin += ((Android) phones[i]).getHotspotMin();
         }   
      }   
      return totalHotspotMin;
   }

   /**
    * Calculates total iMessage count for iPhones.
    *
    * @return int
    */
   public int calculateTotalIMessages() {
      int totalIMessages = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof IPhone) {
            totalIMessages += ((IPhone) phones[i]).getIMessages();
         }   
      }   
      return totalIMessages;
   }

   /**
    * Returns string for summary report.
    *
    * @return String
    */
   public String summary() {
      DecimalFormat dfmt = new DecimalFormat("$#,000.00");
      String summary = "------------------------------"
         + "\nSummary for " + getName()
         + "\n------------------------------"
         + "\nNumber of cell phones: " + phones.length
         + "\nTexts: " + calculateTotalTexts()
         + "\nTalk Minutes: " + calculateTotalMinutes()
         + "\nData: " + calculateTotalData()
         + "\nHotspot Minutes: " + calculateTotalHotspotMin()
         + "\niMessages: " + calculateTotalIMessages()
         + "\nBill Total: " + dfmt.format(calculateTotalBill());
      return summary;
   }

   /**
    * Returns string for different rates.
    *
    * @return String
    */
   public String rates() {
      DecimalFormat dfmt = new DecimalFormat("0.00");
      String rates = "\n------------------------------\n"
         + "Rates for " + getName()
         + "\n------------------------------\n"
         + "FlipPhone Talk Rate: $" + dfmt.format(FlipPhone.TALK_RATE)
         + "   Text Rate: $" + dfmt.format(FlipPhone.TEXT_RATE)
         + "\nSmartPhone Talk Rate: $" + dfmt.format(SmartPhone.TALK_RATE)
         + "   Text Rate: $" + dfmt.format(SmartPhone.TEXT_RATE)
         + "   Max Talk Time: " + SmartPhone.MAX_TALK_TIME
         + "\n   iPhone iMessage Rate: $" + dfmt.format(IPhone.IMESSAGE_RATE)
         + "\n   Android Hotspot Rate: $" + dfmt.format(Android.HOTSPOT_RATE)
         + "\n";
      return rates;
   }

   /**
    * Returns string of phones sorted by number.
    *
    * @return String
    */
   public String listByNumber() {
      Arrays.sort(phones);
      String listByNumber = "------------------------------"
         + "\nCell Phones by Number"
         + "\n------------------------------\n";
      for (CellPhone phone : phones) {
         listByNumber += "\n" + phone.toString() + "\n";
      }
      return listByNumber;
   }

   /**
    * Returns string of phones sorted by bill.
    *
    * @return String
    */
   public String listByBill() {
      Arrays.sort(phones, new CellPhoneBillComparator());
      String listByBill = "------------------------------"
         + "\nCell Phones by Billing Amount"
         + "\n------------------------------\n";
      for (CellPhone phone : phones) {
         listByBill += "\n" + phone.toString() + "\n";
      }
      return listByBill;
   }

   /**
    * Returns string excluded records.
    *
    * @return String
    */
   public String excludedRecordsList() {
      String excRecList = "------------------------------"
         + "\nExcluded Records"
         + "\n------------------------------\n";
      for (String unrecPhones : excludedRecords) {
         excRecList += "\n" + unrecPhones + "\n";
      }
      return excRecList;
   }
}

5 个答案:

答案 0 :(得分:1)

CellPhone[] newPhones = new CellPhone[phones.length - 1]; 
phones = newPhones;

这一行声明了一个新数组,但是没有填充任何值,它们都是null。您需要遍历newPhones并分配所有值。

CellPhone[] newPhones = new CellPhone[phones.length - 1]; 
for (int i = 0; i < newPhones.length; i++) {
  newPhones[i] = phones[i];
}
phones = newPhones;

答案 1 :(得分:0)

请将phones[phones.length - 1] = null;移出for循环。然后,您需要一些代码来复制phonesnewPhones之间的数据,并将这些代码移到for循环之外。

for (int i = deleteIndex; i < phones.length - 1; i++) {
    phones[i] = phones[i + 1];
    // Move three lines of code
    phones[phones.length - 1] = null; // <= Problem here
    CellPhone[] newPhones = new CellPhone[phones.length - 1];
    // Need some code to copy data
    phones = newPhones;
}

最后,无论如何,你必须将数据复制到新数组,所以我认为你应该从头开始复制它:

CellPhone[] newPhones = new CellPhone[phones.length - 1];
int oldIndex = 0, newIndex = 0;
while (oldIndex < phones.length) {
    if (oldIndex != deleteIndex) { // Skip copying deleted number
        newPhones[newIndex++] = phones[oldIndex];
    }

    oldIndex++;
}

答案 2 :(得分:0)

当您尝试在循环和复制时将最后一个元素设置为null时,问题应该发生在循环中:

if (deleteIndex > -1) {
     for (int i = deleteIndex; i < phones.length - 1; i++) {
        phones[i] = phones[i + 1];
        phones[phones.length - 1] = null; //<====== This line
        CellPhone[] newPhones = new CellPhone[phones.length - 1];
        phones = newPhones;
     }
     return true;
  }
  else {
     return false;
  }

在任何循环时间,第一行将下一个元素复制到当前索引,但每次将最后一个元素设置为null时都会出现问题,因为这会在将其复制到前一个元素之前发生数组。

我建议改为:

    if (deleteIndex > -1) {
         for (int i = deleteIndex; i < phones.length - 1; i++) {
            phones[i] = phones[i + 1];
         }

         CellPhone[] newPhones = new CellPhone[phones.length - 1];
         System.arraycopy(phones, 0, newPhones, 0, phones.length - 1);
         return true;
      }
      else {
         return false;
      }

答案 3 :(得分:0)

if (deleteIndex > -1) {
  CellPhone[] tmp = new CellPhone[phones.length - 1]; // smaller array

   //copy everything before deleteIndex
  System.arraycopy(phones, 0, tmp, 0, deleteIndex);

   //copy everything after deleteIndex
  if (deleteIndex < phones.length - 1)
  {
     System.arraycopy(phones, deleteIndex+1, tmp, deleteIndex,
                      phones.length - 1 - deleteIndex);
  }

  phones=tmp; // use new smaller array
}

答案 4 :(得分:0)

阵列很头疼,我更喜欢ArrayLists;试试这个

public boolean deletePhone(String numberIn) {
    boolean phoneExists = false;
    List<String> phoneList = new ArrayList<>();
    for (int i = 0; i < phones.length; i++) {
        if (!numberIn.equals(phones[i].getNumber())) {
            phoneList.add(phones[i].getNumber());
            phoneExists = true;
        }
    }
    phones = phoneList.toArray(new String[phoneList.size()]);
    return phoneExists;
}

如果你不喜欢列表,这里只是使用数组的解决方案:

public boolean deletePhone(String numberIn) {
    boolean phoneExists = false;
    String[] newPhones;
    int newLength = phones.length;

    for (int i = 0; i < phones.length; i++) {
        if (numberIn.equals(phones[i].getPhones())) {
            phones[i] = null;
            newLength--;
            phoneExists = true;
        }
    }

    newPhones = new CellPhone[newLength];
    for (int i = 0, j = 0; i < phones.length; i++) {
        if (phones[i] != null) {
            newPhones[j++] = phones[i];
        }
    }

    phones = newPhones;
    return phoneExists;
}