Comparing two dates using Comparable interface

2019-07-16 15:24发布

I am currently designing a GUI for a bank database application. In my GUI I have a "List accounts opened before" button that I am trying to code to list all of the accounts in the database in a text area that have dates before a date that the user inputs into a text field. I am very confused about the implementation behind a Comparable interface and how to correctly compare two dates in a array of objects. In my mind my ShowBefore methods logic is correct, however I think that is not the case and I do not know why. My problem is with the BankDatabase's showBefore() method, Date's compareTo() method, and the GUI's ShowAllActions button. Any help would be greatly appreciated. I receive

"Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at BankDatabase.showBefore(BankDatabase.java:234) at TransactionManager.showAllAccountsActionPerformed(TransactionManager.java:474) at TransactionManager.access$1200(TransactionManager.java:17) at TransactionManager$13.actionPerformed(TransactionManager.java:202) "

When I input any date into the gui.

*I only posted the bare minimum methods required

public class BankDatabase
{
private static final int GROW_SIZE = 2;
private static final int NOT_FOUND = -1;
private static final int ARRAY_SIZE = 100; //i added this
private Account[] bank;
private int num;

/**
default constructor
*/
public BankDatabase()
{
  num = 0;
  bank = new Account[ARRAY_SIZE];
}

public String showBefore( Date prevDate) 
{
  String temp = new String();
  for ( int i = 0; i < size(); i++)
  {
     if ( bank[i].getDate().compareTo(prevDate) == -1 )
     {
        temp += bank[i].toString(); // 
        temp += "\n";
     }
  }
  return temp;
}

import java.util.Calendar;
import java.util.StringTokenizer;

public class Date implements Comparable {
   private int invalidCheck = 0;
   private int day;
   private int month;
   private int year;

   /**
   Parameterized Constructor.
   @param d date
   */
   public Date(String d)
   {
      StringTokenizer st = new StringTokenizer(d, "/");
      month = Integer.parseInt(st.nextToken());
      day = Integer.parseInt(st.nextToken());
      year = Integer.parseInt(st.nextToken());
   }

   /**
   Copy Constructor.
   @param d date
   */
   public Date(Date d)
   {
      month = d.month;
      day = d.day;
      year = d.year;
   }

   /**
   Creates an instance with todays date
   */
   public Date()
   {
      Calendar c = Calendar.getInstance();
      this.day = c.get(Calendar.DAY_OF_MONTH);
      this.month = c.get(Calendar.MONTH) + 1;
      this.year = c.get(Calendar.YEAR);
   }

   /**
   Compare “this” with (Date) o; if “this” is before o, return -1; if “this” is equal
   to o return 0; if “this” is after o, return 1.
   @param o
   @return the value of the date
   */
   public int compareTo(Object o)
   {
      Date d = new Date((Date) o);

      if(d.year > year)
         return -1;
      if(d.year < year)
         return 1;
      if(d.month > month)
         return -1;
      if(d.month < month)
         return 1;
      if(d.day > day)
         return -1;
      if(d.day < day)
         return 1;
      return 0;
   }

   /**
   checks to see if certain dates are valid. Also checks 
   if it is a leap year to verify the correct amount of days 
   in February.
   @return true if the date is valid, false otherwise
   */
   public boolean isValid()
   {
      if (( month == Month.JAN || month == Month.MAR
            || month == Month.MAY || month == Month.JUL
            || month == Month.OCT || month == Month.OCT
            || month == Month.DEC )
            && ( day <= Month.DAYS_ODD && day > invalidCheck ) )
         return true;
      if (( month == Month.APR || month == Month.JUN
            || month == Month.SEP
            || month == Month.NOV )
            && ( day <= Month.DAYS_EVEN && day > invalidCheck ) )
         return true;

      boolean leapYear = false;
      if ( year % Month.QUADRENNIAL == invalidCheck 
            || year % Month.CENTENNIAL == invalidCheck
            || year % Month.QUATERCENTENNIAL == invalidCheck )
      {
         leapYear = true;
      }
      if (leapYear)
      {
         if (month == Month.FEB && day <= Month.DAYS_FEB + 1)
            return true;
      }
      if (month == Month.FEB && day <= Month.DAYS_FEB)
         return true;
      return false;
   }

   /**
   Return the name and date of the TeamMember as a String.
   @return name::price as a string.
    */
   public String toString()
   {
      return month + "/" + day + "/" + year;
   }

   /**
   day,month, and year are equal if they have the 
   same day, month, and year
   @param obj
   @return true if they are equal, false otherwise.
   */
   public boolean equals(Object obj)
   {
      if (obj instanceof Date)
      {
         Date d = (Date) obj;
         return d.day == day && d.month == month && d.year == year;
      }
      return false;
   }
}

public abstract class Account
{
   private static int numAccount = 1000; //incremented by 1 for each acc op.
   protected final int PERCENTAGE = 100;
   protected final int MONTH_PER_YEAR = 12;
   protected Profile holder; //account holder's profile
   protected int accNumber; //a sequence number from numAccount
   protected double balance;
   protected Date openOn; //the date the account is opened on

   /**
    parameterized constructor
    @param name String that will be the name
    @param phone String that will be the phone associated with the account
    */
   public Account(String name, String phone)
   {
      holder = new Profile(name, phone);
      accNumber = numAccount++;
      balance = 0;// 0 if deposit has to happen after
      openOn = new Date();
   }

   public Date getDate()
   {
      return openOn;
   }

public abstract String toString(); //subclass must implement this method

public class TransactionManager extends javax.swing.JFrame
{
   BankDatabase database = new BankDatabase();
   TransactionSimulator sim = new TransactionSimulator();
   ButtonGroup accType = new ButtonGroup();
   private Vector client;

   /**
    Creates new form TransactionManager
    */
   public TransactionManager()
   {
      initComponents();
      database = new BankDatabase();
      accType.add(checking);
      accType.add(savings);
      accType.add(moneyMarket);
      cbSpecialSavings.setEnabled(false);
      client = new Vector<String>();
   }
   private void showAllAccountsActionPerformed(java.awt.event.ActionEvent evt)                                                
   {                                                    
      Date openOn = new Date(dateBefore.getText());
      outputArea.append(database.showBefore(openOn));
   }   

2条回答
beautiful°
2楼-- · 2019-07-16 15:58
  if(d.month > month)
     return -1;
  if(d.month > month)
     return 1;

You have equivalent if clauses in equals method.

查看更多
Deceive 欺骗
3楼-- · 2019-07-16 16:09

About your showBefore() at least make some additional checks

public String showBefore( Date prevDate)
{
    StringBuilder builder = new StringBuilder("");
    for ( int i = 0; i < size(); i++)
    {
        Account account = bank[i];
        if (account != null) {
            Date date = account.getDate();
            if (date != null && date.compareTo(prevDate) == -1 ) {
                builder.append(account.toString() + "\n")
            }
        }
    }
    return builder.toString();
}

and keep in mind what StringBuilder is not synchronized

In other case read more about Java 8 features such as Stream API, New Date/Time API, lambda

public String showBefore(LocalDate prevDate)
{
    StringBuilder builder = new StringBuilder("");
    Arrays.asList(bank).parallelStream().forEach(account -> {
        if (account != null) {
            LocalDate date = account.getDate();
            if (date != null && date.compareTo(prevDate) == -1 ) {
                builder.append(account.toString()).append("\n");
            }
        }
    });
    return builder.toString();
}
查看更多
登录 后发表回答