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
\$\endgroup\$
  • \$\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\$ – rdllopes Jun 22 '16 at 11:36
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();
}
\$\endgroup\$
  • 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\$ – Samuel.s Jun 22 '16 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\$ – RobAu Jun 22 '16 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.