2
\$\begingroup\$

I am writing a program that reads a DAT file with names. The names are stored in an ArrayList of Type Name, the Name object can hold the first, middle and last name. Once the names are stored in the ArrayList they are then sorted alphabetically by last name and written back to the file. I wanted to know what I can do to improve efficiency or eliminate redundant code. Note: This Program does work.

Name.java

public class Name 
{
private String firstName;
private String midName;
private String lastName;
public Name(String firstName, String lastName)
{
 this.firstName=firstName;
 this.lastName=lastName;
 this.midName="";
}
public Name(String firstName, String midName, String lastName)
{
 this.firstName=firstName;
 this.midName=midName;
 this.lastName=lastName;
}
public String getFirstName()
{
 return firstName;
}
public String getMidName()
{
 return midName;
}
public String getLastName()
{
 return lastName;
}
public String toString()
{
 if(midName.equals(""))
 {
 return "First Name: " + getFirstName()
 + "\nLast Name: " + getLastName();
 }
 return "First Name: " + getFirstName()
 + "\nMiddle Name: " + getMidName()
 + "\nLast Name: " + getLastName();
}
 }

Database.java

public class Database
{
public static final String FileName="Name Database.dat";
private ArrayList <Name> name;
public Database()
{
 name=new ArrayList<Name>();
 getData();
}
public void getData()
{
 BufferedReader in=null;
 StringTokenizer tokenizer=null;
 String fullName, firstName, midName, lastName;
 fullName=firstName=midName=lastName="";
 try{
 in=new BufferedReader(new FileReader(FileName));
 if(in.ready())
 {
 while((fullName=in.readLine())!=null)
 {
 firstName=midName=lastName="";
 tokenizer=new StringTokenizer(fullName);
 if(tokenizer.hasMoreTokens())
 {
 firstName=tokenizer.nextToken();
 }
 if(tokenizer.hasMoreTokens())
 {
 midName=tokenizer.nextToken();
 }
 if(tokenizer.hasMoreTokens())
 {
 lastName=tokenizer.nextToken();
 name.add(new Name(firstName, midName, lastName));
 }else{
 name.add(new Name(firstName, midName));
 }
 }
 }
 }
 catch(Exception e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 finally{
 try{
 in.close();
 }
 catch(IOException e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 }
}
public void sortByLastName()
{
 ArrayList <Name> newName=new ArrayList<Name>();
 String word=name.get(0).getLastName();
 int min;
 int pos;
 while(!name.isEmpty())
 {
 word=name.get(0).getLastName();
 min=0;
 pos=0;
 for(int i=0; i<name.size(); i++)
 {
 if(word.compareTo(name.get(i).getLastName())<min)
 {
 word=name.get(i).getLastName();
 min=word.compareTo(name.get(i).getLastName());
 pos=i;
 }
 }
 newName.add(0, name.remove(pos));
 }
 name=newName;
}
public void sendToFile()
{
 BufferedWriter out=null;
 try{
 out=new BufferedWriter(new FileWriter(FileName));
 clearDataFile();
 for(int i=0; i<name.size(); i++)
 {
 out.write(name.get(i).getFirstName() + " " + name.get(i).getMidName() + " " + name.get(i).getLastName());
 out.newLine();
 }
 }
 catch(Exception e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 finally{
 try{
 out.close();
 }
 catch(IOException e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 }
}
public void clearDataFile()
{
 FileOutputStream out=null;
 FileChannel file=null;
 try{
 out=new FileOutputStream(FileName);
 file=out.getChannel();
 file.truncate(0);
 }
 catch(Exception e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 finally{
 try{
 out.close();
 file.close();
 }
 catch(IOException e){
 System.out.println(e.getCause());
 System.exit(1);
 }
 }
}
public void printData()
{
 for(int i=0; i<name.size(); i++)
 {
 System.out.println(name.get(i) + "\n");
 }
}
}

Sample Input from File

Stephen Forsyth
Owen Hodges
Sally James
Gavin Blake
Carl Mitchell
Caroline Bower
Maria Murray
Bernadette Alsop
Ella Reid
Diane Blake

Sample Output to File

Bernadette Alsop
Diane Blake
Gavin Blake
Caroline Bower
Stephen Forsyth
Owen Hodges
Sally James
Carl Mitchell
Maria Murray
Ella Reid
asked Jun 22, 2016 at 8:48
\$\endgroup\$
1
  • \$\begingroup\$ Do you need to write the sorting algorithm by yourself? Do you know there are plenty of sorting algorithms already implemented, right? For instance, you can use Collections.sort that uses TimSort since java 7. \$\endgroup\$ Commented Jun 22, 2016 at 11:36

1 Answer 1

2
\$\begingroup\$

Use existing Java naming convention

  • Only classes, interfaces and enums should start with a Capital.
  • Fields should be camelCase
  • Static fields should be ALL_UPPERCASE_WITH_UNDERSCORES

Also, if you have an Collection of items, it is normally either called -List, -Map or a plural is used, so you can recognize a collection faster when reading code.

public class Database
{
 public static final String FILE_NAME="Name Database.dat";
 private ArrayList<Name> names;
...

Use existing Java constructs

Java provides many useful constructs that allow you to minimize your code. In your case, use the Interface Comparable<T>.

This way, you can sort by using Collections.sort() using Java's built-in sort mechanism.

public class Name implements Comparable<Name> {
 ..
 @Override
 public int compareTo(Name o) {
 int lastnameCompare = this.getLastName().compareTo(o.getLastName());
 //exam
 if (lastnameCompare == 0)
 {
 return this.getFirstName().compareTo(o.getFirstName());
 }
 else
 {
 return lastnameCompare;
 }
 }
 ..
}

Also, use try-with-resources:

 try (BufferedReader in=new BufferedReader(new FileReader(fileName))) {
 } catch (FileNotFoundException e) {
 ...
 } catch (IOException e) {
 ...
 }

This leverages the AutoClosable interface of the Reader so you don't need to close it manually.

Reuse constructors

To optimize re-use of code, try to have one constructor that does the 'real' work, and make convenience constructors for easy coding.

public Name(String firstName, String lastName)
{
 this(firstName, "", lastName);
}
public Name(String firstName, String midName, String lastName)
{
 this.firstName=firstName;
 this.midName=midName;
 this.lastName=lastName;
}

Make your code reuseable

Your Database class can only be used for a single file. If you would pass the filename in the contructor, you can re-use your database class for any file!

public class Database
{
 public final String fileName;
 public Database (String fileName)
 {
 this.fileName = fileName;
 }
 ....
}

Try not to repeat yourself

public String toString()
{
 StringBuilder result = new StringBuilder();
 result.append("First name:" + getFirstName() + "\n")
 if(!midName.isEmpty()) {
 result.append("Middle name:" + getMiddleName() + "\n")
 }
 result.append("Last name:" + getLastName() + "\n");
 return result.toString();
}
h.j.k.
19.3k3 gold badges37 silver badges93 bronze badges
answered Jun 22, 2016 at 12:48
\$\endgroup\$
2
  • 1
    \$\begingroup\$ First off I appreciate your response, it was quite helpful. However, in regard to using the built-in constructs, what would need to be done if I also wanted to create an additional method in the Database class that sorted the Name objects by first name? \$\endgroup\$ Commented Jun 22, 2016 at 18:23
  • \$\begingroup\$ You can create a custom Comparator<Name> and pass it as second argument to the Collections.sort(). You can create a static method on Name that returns this Comparator. \$\endgroup\$ Commented Jun 22, 2016 at 21:10

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.