Entering multiple things in to one array in java - java

I am quite new to java but have a project i need to complete and am stuck on a certain part.
I want to allow the user to enter a route including, start destination, an end destination, and a number of stops. I have been able to do this, but then i want the user to have the ability of being able to add the same things again, to the same array. without deleting the existing route
here is the code i have so far
import java.util.Scanner;
import java.util.Arrays;
public class main {
public static void main(String[] args){
menu();
}
public static void menu(){
Scanner scanner = new Scanner(System.in);
System.out.println("enter 1 to input a new route");
int option = scanner.nextInt();
if(option==1){
inputRoute();
}
}
public static void inputRoute(){
Scanner scanner = new Scanner(System.in);
System.out.println("Please Enter Starting Destination");
String startDest = scanner.next();
System.out.println("Please Enter End Destination");
String endDest = scanner.next();
System.out.println("Please Enter Number of stops");
int numberOfStops = scanner.nextInt();
String[] stops = new String[numberOfStops];
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
stops[i-1] = scanner.next();
}
System.out.println(Arrays.toString(stops));
menu();
}
}
however when this runs, if i go back and enter in another route, it will just delete the existing route.
Is there any way of appending the next route to the end of that array or any way of doing this?
thank you

Like crush said. Rather than use a normal array of strings, use an ArrayList<String> object. Or even an ArrayList<String[]> and stash each individual route in there.

First of all you will need to declare the stops array as an instance variable, otherwise you will always be creating a new array whenever you call the method inputRoute().
and then to preserve old entries i can think of two ways-->
--> modify the loop as below...
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
if(stops!=null) //without the if condition it will also append null in the start
stops[i-1]=stops[i-1]+", "+ scanner.next(); // you can you any separator
else
stops[i-1]=scanner.next();
}
--> or you can ArrayList or any other Collection that provides auto increment

Try declaring stops as a global variable. (right below the class line)
Also I would recommend using an ArrayList, List something on those lines

You can't use an array for this (without constantly re-allocating them) as Arrays are fixed in size once created.
Use an ArrayList though and you can add as many items as you like whenever you like.

The easy (and slightly wrong) solution would be to make your array a static array that is defined outside any method. That will get you going (although you will have to make the array big enought.
Other recommendations:
Capatilize your Main class--avoids confusiong (even moreso if you
don't call it main!)
Make your public static void main method do
this: new Main()
Then get rid of all the other statics.
Use a collection instead of an array.
instead of adding each entry into the array separately (which will make EVERYTHING harder for you), create a second class with 3 fields (start, end, stop) and each time you input another record, "new" an instance of the second class, place the three things into the new instance and place that instance on your collection.
It may seem arbitrary and unnecessary right at this minute, but if you have ANY follow-on work to do on this class these things will make your life easier. If any seems confusing or you want to understand why, feel free to ask in the comments.

I think this will help you.
Main file.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
menu();
}
public static void menu(){
List<Route> routeList = new ArrayList<Route>();
Scanner scanner = new Scanner(System.in);
System.out.println("enter 1 to input a new route");
int option = scanner.nextInt();
if(option==1){
routeList.add(inputRoute());
}
System.out.println("Complete list of routes is "+routeList);
}
public static Route inputRoute(){
Route route = new Route();
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter the name of the route");
String name = scanner.next();
route.setName(name);
System.out.println("Please Enter Starting Destination");
String startDest = scanner.next();
route.setStartLocation(startDest);
System.out.println("Please Enter End Destination");
String endDest = scanner.next();
route.setEndLocation(endDest);
System.out.println("Please Enter Number of stops");
int numberOfStops = scanner.nextInt();
if(numberOfStops > 0){
route.setStopList(new ArrayList<String>());
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
route.getStopList().add(scanner.next());
}
System.out.println("current entered route is "+route);
menu();
}
return route;
}
}
Route file:
import java.util.List;
public class Route {
String name ;
String startLocation;
String endLocation;
List<String> stopList;
public Route() {
}
public Route(String name, String startLocation, String endLocation, List<String> stopList) {
this.name = name;
this.startLocation = startLocation;
this.endLocation = endLocation;
this.stopList = stopList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStartLocation() {
return startLocation;
}
public void setStartLocation(String startLocation) {
this.startLocation = startLocation;
}
public String getEndLocation() {
return endLocation;
}
public void setEndLocation(String endLocation) {
this.endLocation = endLocation;
}
public List<String> getStopList() {
return stopList;
}
public void setStopList(List<String> stopList) {
this.stopList = stopList;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Route route = (Route) o;
if (endLocation != null ? !endLocation.equals(route.endLocation) : route.endLocation != null) return false;
if (name != null ? !name.equals(route.name) : route.name != null) return false;
if (startLocation != null ? !startLocation.equals(route.startLocation) : route.startLocation != null)
return false;
if (stopList != null ? !stopList.equals(route.stopList) : route.stopList != null) return false;
return true;
}
#Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (startLocation != null ? startLocation.hashCode() : 0);
result = 31 * result + (endLocation != null ? endLocation.hashCode() : 0);
result = 31 * result + (stopList != null ? stopList.hashCode() : 0);
return result;
}
#Override
public String toString() {
return "Route{" +
"name='" + name + '\'' +
", startLocation='" + startLocation + '\'' +
", endLocation='" + endLocation + '\'' +
", stopList=" + stopList +
'}';
}
}

Related

Trying to give my program Manners (JAVA Beginner)

Only started learning code this week so I'm probably just getting too far ahead of myself, but any help would be amazing!
I have been working to try and give my programme two different personality traits: formal and informal.
I've tried to do it by using the boolean "MANNERS" which determines every reference thereafter (including name choices) because functions can be checked against this single boolean.
Each time myName is references, I want it to select, at random; either a formalNameRef or an informalNameRef, depending on what it's set "Manners" are to.
In pieces, this worked, but once I put it all together it seems to have stopped working ------->
public class nameChoice{
//A list of formal things to call me
public static String formName(){
ArrayList<String> formNames = new ArrayList<String>();
formNames.add("Master");
formNames.add("Sir");
formNames.add("Mr Smith");
Random formalNs = new Random();
formalNs.nextInt(3);
return formNames.get(formalNs.nextInt(3));
}
//A list of informal things to call me
public static String nickName(){
ArrayList<String> nickNames = new ArrayList<String>();
nickNames.add("Ol' Fella");
nickNames.add("Buddy");
nickNames.add("Dude");
nickNames.add("Mate");
nickNames.add("John");
Random nickNs = new Random();
nickNs.nextInt(5);
return nickNames.get(nickNs.nextInt(4));
}
public static void main(String[] args){
//keeps saying "value of manners is not used"??could this be the problem??
boolean manners;
//as default, it choices a formal name
String myName;
// Asks me if I want it to be formal (have "manners")
System.out.println("Do you want me to be formal?");
Scanner formal = new Scanner(System.in);
String formalInput = formal.next();
//If formal, turn manners ON
if (formalInput.equals("yes")||formalInput.equals("yep")){
manners = true;
}
//If informal, turn manners OFF
else {manners = false;};
//If manners are ON, choose random name from formName()
if (manners = true){
myName = formName();
}
//Else choose from nickName()
else{myName = nickName();};
System.out.println("Hello " + myName + ", how are you?");
Scanner feeling = new Scanner(System.in);
String feelingInput = feeling.next();
if (feelingInput.equals("dunno")){
System.out.println("Huh..");
}
else{
System.out.println("Interesting...how much sleep have you had " + myName + "?");
System.out.println(myName);
System.out.println(myName);
}
}
}
If it says "Dude" the first time, it always says "Dude".
If it says "Sir" the first time, it always says "Sir".
(not what I want, I'm trying to pick a different name every time from the same array)
I'm guessing I need to put some sort of loop somewhere, to make it keep picking names at random, but I have no idea where. I would LOVE to know. TY
You check for a condition using ==, not = .. So your manners boolean is being SET to TRUE every time you pass by if (manners = true).
1) Make the ArrayList<String> Global and null.
if (manners == true) myName = formName();
else {myName = nickName();};
is where you would add to the list. myName is just a String, you want an ArrayList<String>.
2) Create a randInt method like the one below.
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
3) Make the following changes.
public static `ArrayList<String>` formName(){
ArrayList<String> formNames = new ArrayList<String>();
formNames.add("Master");
formNames.add("Sir");
formNames.add("Mr Smith");
return formNames;
}
Create the list variable and initialize to null.
ArrayList<String> myName = null;
Then you would assign the list in the following manner.
myName = formName();
This way you will always get a randomly picked name from the list.
System.out.println("Hello " + myName.get(randInt(0, (myName.length - 1)) + ", how are you?");
Also
if (manners = true){
myName = formName();
}
To check boolean conditions it's ==, NOT =. What you're doing above is setting the value of manners to be true, making it always true.
EDIT: Example working code
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class nameChoice
{
public static ArrayList<String> formName()
{
ArrayList<String> formNames = new ArrayList<String>();
formNames.add("Master");
formNames.add("Sir");
formNames.add("Mr Smith");
return formNames;
}
public static ArrayList<String> nickName()
{
ArrayList<String> nickNames = new ArrayList<String>();
nickNames.add("Ol' Fella");
nickNames.add("Buddy");
nickNames.add("Dude");
nickNames.add("Mate");
nickNames.add("John");
return nickNames;
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void main(String[] args)
{
boolean manners;
ArrayList<String> myName;
System.out.println("Do you want me to be formal?");
Scanner formal = new Scanner(System.in);
String formalInput = formal.next();
if (formalInput.equals("yes") || formalInput.equals("yep"))
{
manners = true;
}
else
{
manners = false;
}
if (manners == true)
{
myName = formName();
}
else
{
myName = nickName();
}
System.out.println("Hello " + myName.get((randInt(0, (myName.size() - 1)))) + ", how are you?");
}
}

Trying to utilize an input.txt file into a output.txt file in Java

I am trying to test my application by printing into an output.txt file. There is an input.txt file that already contains four honor students and at least two with the same GPA of 3.9, and three that are not honors students. The results should be sent to the output.txt file. The output.txt file should contain:
1) All of the students
2) The best student
3) Number of honors students in the list
4) Honors students
The input.txt file that I created contains the following (in order) last names, first names, id, GPA, and year.
The class TestStudents prints the input.txt file. However, I need it to utilize the input.txt file in order to print the above mentioned output.txt file. Thank you very much.
Student class -
public class Student
{
String lastName, firstName, id;
double gpa;
int year;
public Student (String lastName, String firstName, String id,
double gpa, int year)
{
this.lastName = lastName;
this.firstName = firstName;
this.id = id;
this.gpa = gpa;
this.year = year;
}
public String toString()
{
return this.lastName + ", " + this.firstName + ": " + this.id + " "
+ this.gpa + " " + this.year;
}
public double getGPA()
{
return gpa;
}
public boolean isBetter (Student s)
{
return (this.gpa > ((Student)s).getGPA());
}
public boolean isHonors()
{
if (this.gpa >= 3.5)
{
return true;
}
else
{
return false;
}
}
}
CS152 class -
import java.util.*;
import java.io.*;
public class CS152
{
public static final int MAXSIZE = 22;
private static int size = 0;
public static Student[] createList (Scanner scan) throws IOException
{
Student[] list = new Student [MAXSIZE];
return populateList (list, scan);
}
private static Student[] populateList (Student[] list, Scanner scan)
{
Student s;
if (size < MAXSIZE && scan.hasNext())
{
s = new Student (scan.next(), scan.next(), scan.next(),
scan.nextDouble(), scan.nextInt());
list[size] = s;
size++;
System.out.println (s);
return populateList (list, scan);
}
else
{
return list;
}
}
public static int getSize()
{
return size;
}
// Returns String of all students. Variable n is actual size of the list.
// Assume that n is positive. Recursive code.
public static String toString (Student[] list, int n)
{
String s = " ";
if (n == 1)
{
return s += list[0];
}
else
{
s += list[n].toString() + "\n";
s += "\n";
}
return s + toString (list, n - 1);
}
// Returns the best student. Must use method isBetter in the code.
// Variable n is actual size of the list. Assume that n is positive.
public static Student findBestStudent (Student[] list, int n)
{
if (n == 1)
{
return list[0];
}
else if (list[n].isBetter (list[n - 1]))
{
return list[n];
}
else
{
return findBestStudent (list, n - 1);
}
}
// Returns the number of honor students in the list.
// Must call the method isHonors(). Variable n is actual size of the list.
// Assume that n is positive.
public static int countHonors (Student[] list, int n)
{
if (n == 0)
{
return 0;
}
else if (list[n].isHonors())
{
return 1 + countHonors (list, n - 1);
}
else
{
return countHonors (list, n - 1);
}
}
static ArrayList<Student> studentsList = new ArrayList<Student>();
public static ArrayList <Student> honorsStuds (Student[] list, int n)
{
if (n == 0)
{
return studentsList;
}
else
{
boolean currentIsHonors = list[n - 1].isHonors();
if (currentIsHonors)
{
studentsList.add(list[n - 1]);
return honorsStuds (list, n - 1);
}
else
{
return honorsStuds (list, n - 1);
}
}
}
}
TestStudents class -
import java.io.*;
import java.util.*;
public class TestStudents
{
public static void main (String[] args) throws IOException
{
File input = new File ("input.txt");
Scanner scan = new Scanner (input);
Student[] studentArray = CS152.createList (scan);
}
}
I incorporated the FileWriter into the TestStudents class. A list of all students is now displayed. I am still having difficulties trying to call the methods findBestStudent, countHonors, and honorsStuds and implementing them into TestStudents. Here is the revised TestStudents class:
TestStudents class -
import java.io.*;
import java.util.*;
public class TestStudents
{
public static void main (String[] args) throws IOException
{
File input = new File ("input.txt");
Scanner scan = new Scanner (input);
System.out.println ("All students: ");
Student[] studentArray = CS152.createList (scan);
File output = new File ("output.txt");
FileWriter fWriter = new FileWriter (output);
PrintWriter pWriter = new PrintWriter (fWriter);
pWriter.println (input);
pWriter.close();
}
}
To write to a file, you need a FileWriter.
Using a FileWriter and Try-with-resources, usage would look something like this:
try(FileWriter w = new FileWriter(new File("output.txt"))) {
w.append("Some string");
} catch (IOException ex) {
Logger.getLogger(Output.class.getName()).log(Level.SEVERE, null, ex);
}
If you don't use a try-with-resources, make sure to close() the Writer to make sure resources do not leak. In fact, you should also make sure to close your Scanner as well, as leaving it un-closed will leak resources.
In the future, ask one question per post.
To access your Students, you just need to read them from the array.
System.out.println(studentArray[0].getGPA()); // prints the GPA of the first student
for (int i=0; i<CS152.getSize(); i++) {
System.out.println(studentArray[i]); // prints every Student
}
[[Note that this design of having a long array with null elements at the end with CS152.class telling you how many are filled is bad design. I would have the read procedure return a List<Student>, which manages its own length. Given the name of the class is CS152, however, this is probably either given to you by the teacher of CS-152 or done previously, so I'll work with what you have.]]

How do I have a program create its own variables with Java?

I would like to start off by saying that if this is common knowledge, please forgive me and have patience. I am somewhat new to Java.
I am trying to write a program that will store many values of variables in a sort of buffer. I was wondering if there was a way to have the program "create" its own variables, and assign them to values.
Here is an Example of what I am trying to avoid:
package test;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
int inputCacheNumber = 0;
//Text File:
String userInputCache1 = null;
String userInputCache2 = null;
String userInputCache3 = null;
String userInputCache4 = null;
//Program
while (true) {
Scanner scan = new Scanner(System.in);
System.out.println("User Input: ");
String userInput;
userInput = scan.nextLine();
// This would be in the text file
if (inputCacheNumber == 0) {
userInputCache1 = userInput;
inputCacheNumber++;
System.out.println(userInputCache1);
} else if (inputCacheNumber == 1) {
userInputCache2 = userInput;
inputCacheNumber++;
} else if (inputCacheNumber == 2) {
userInputCache3 = userInput;
inputCacheNumber++;
} else if (inputCacheNumber == 3) {
userInputCache4 = userInput;
inputCacheNumber++;
}
// And so on
}
}
}
So just to try to summarize, I would like to know if there is a way for a program to set an unlimited number of user input values to String values. I am wondering if there is a way I can avoid predefining all the variables it may need.
Thanks for reading, and your patience and help!
~Rane
You can use Array List data structure.
The ArrayList class extends AbstractList and implements the List
interface. ArrayList supports dynamic arrays that can grow as needed.
For example:
List<String> userInputCache = new ArrayList<>();
and when you want to add each input into your array like
if (inputCacheNumber == 0) {
userInputCache.add(userInput); // <----- here
inputCacheNumber++;
}
If you want to traverse your array list you can do as follows:
for (int i = 0; i < userInputCache.size(); i++) {
System.out.println(" your user input is " + userInputCache.get(i));
}
or you can use enhanced for loop
for(String st : userInputCache) {
System.out.println("Your user input is " + st);
}
Note: it is better to put your Scanner in your try catch block with resource so you will not be worried if it is close or not at the end.
For example:
try(Scanner input = new Scanner(System.in)) {
/*
**whatever code you have you put here**
Good point for MadProgrammer:
Just beware of it, that's all. A lot of people have multiple stages in their
programs which may require them to create a new Scanner AFTER the try-block
*/
} catch(Exception e) {
}
For more info on ArrayList
http://www.tutorialspoint.com/java/java_arraylist_class.htm

Calling & Searching through an Arraylist in a different class

I am building a program to read a .txt file and extract the student data and store it in a collection. Then the user is supposed to be able to select several different queries. The query that I am asking for help with is to select all students graduating, for example, in 2014 and then print these results to the screen.
In short, how can I search throw the Arralist stored in ProcessRecords class for students who graduate in, for example, 2014? I just do not understand how to call it from a different class.
Below is my code:
First Class: With the main method
import java.util.*;
import java.io.*;
import java.lang.*;
public class ProcessRecords {
public static void AskUser()
throws Exception {
Scanner preference = new Scanner(System.in);
//Creating a new scanner will allow us to gather user input
boolean flag=true;
//I will use this for my while loop
while (flag) {
System.out.println("What type of Search would you like to run?\n 1)Search for all students\n 2) Search for students graduating in a specific year\n 3)Search for students whose last name begins with a certain string\n");
Query query = new Query(studentRecords);
int searchType=preference.nextInt();
//How would I throw an exception here if the user doesn't enter a number or enters a number less than 1 or great than 4
//This variable will store what type of query the user would like to run
switch(searchType) {
case 1:
System.out.println("Gathering Records for all students\n");
//Call Query Method in the Query Class to return all students in the colletion
case 2:
System.out.println("What graduation year would you like to search for? \n");
String yearsearch=preference.next();
//Call Query Method to return students who are graduating in the specified year
//Pass the "yearsearch" variable to the Query class
case 3:
System.out.println("What string would you like to search for? \n");
String lstsearch=preference.next();
//Call Query Method in the Query Class to return students who have the string in their last name
//Also I need to pass the "lstsearch" variable to the Query class to search through last names
}
}
}
public static void main(String[] args)
throws Exception
{
Scanner input = new Scanner(new File("students.txt"));
//This will import the file
input.nextLine();
//This will skip the headers in the file
System.out.println("Processing file now...");
//Let the user know that the file is being processed
int id;
String last;
String first;
int year;
int i=1;
// Declare variables that we will extract from the file
//Now we will being processing the file with a while loop
List<StudentRecord> studentRecords = new ArrayList<StudentRecord>();
while(input.hasNext())
{
id=input.nextInt();
last=input.next();
first=input.next();
year=input.nextInt();
StudentRecord record = new StudentRecord(id, last, first, year);
studentRecords.add(record);
System.out.println(id + " " + last + " " + first + " " + year + "\n");
}
System.out.println(" You have successfully read and printed from the file!");
for (StudentRecord s : studentRecords)
System.out.println(s.toString());
}
}
Second Class Student Records
public class StudentRecord
{
private int id;
private String last;
private String first;
private int year;
public StudentRecord(int id, String last, String first, int year)
{
this.id=id;
this.last=last;
this.first=first;
this.year=year;
}
public String toString()
{
return id + " " + last + " " + first + " " + year;
}
public int getYear()
{
return year;
}
}
Third Class (The one I am asking for help with)
import java.util.*;
import java.io.*;
public class Query
{
//public static ProcessRecords studentrecord = new ProcessRecords();
private List<StudentRecord> records;
public Query(List<StudentRecord> records) {
this.records = records;
}
public int getYear(int yearSearch) {
int count = 0;
for(StudentRecord record : records) {
if(record.getYear() == yearSearch) {
count++;
}
}
return count;
}
}
Added a new post!
you have to make studentRecords a static variable or an instance variable,
put it like this, above the main :
public static List<StudentRecord> studentRecords ;
public static void main(String[] args)
throws Exception{
studentRecords = new ArrayList<StudentRecord>();
then just call it like this:
ProcessRecords.studentRecords
The easiest solution would be passing the entire list to the getYear method:
public static int getYear(List<StudentRecord> studentRecords, int yearsearch) {
// ProcessRecords processRecords = new ProcessRecords(); <- don't need it
int getYear= yearsearch;
Iterator itr = studentRecords.iterator();
// ...
Your code has multiple problems.
Public variables are discouraged, getters/setters should be used to access object members. Eclipse alt+s, r will generate them for you
Names of your variables are misleading. What is the list you are accessing in Query?
Names of your classes are also (at minimum!) misleading. ProcessRecords as an action in particular seems bad. Shouldn't the class be a noun in this case, like RecordsProcessor? Shouldn't it give a hint to what it is actually doing? StudentYearSearcher?
You do not throw the list, you pass it (it's reference) as an argument, or access it somehow. You throw Exceptions
Answer to your question
There are multiple ways you can do it. One would be to use a singleton pattern and make the list statically accessible. Like this:
class StudentRecord {
static List<StudentRecord> studentRecords;
List<StudentRecord> getStudentRecords() {
if (studentRecords == null) studentRecords= new ArrayList<StudentRecord>();
return studentRecords;
}
//the reest of the class
}
Have your Query class look like this:
public class Query {
private List<StudentRecord> records;
public Query(List<StudentRecord> records) {
this.records = records;
}
public int getYear(int yearSearch) {
int count = 0;
for(StudentRecord record : records) {
if(record.getYear() == yearSearch) {
count++;
}
}
return count;
}
public int otherQuery() {
// code for another query
}
}
Then in your main class:
import java.util.*;
import java.io.*;
import java.lang.*;
public class ProcessRecords {
public static void AskUser(Query query) throws Exception {
// all the code you have right now except the line where you
// create a new Query object
}
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(new File("students.txt"));
//This will import the file
input.nextLine();
//This will skip the headers in the file
System.out.println("Processing file now...");
//Let the user know that the file is being processed
int id;
String last;
String first;
int year;
int i=1;
// Declare variables that we will extract from the file
//Now we will being processing the file with a while loop
List<StudentRecord> studentRecords = new ArrayList<StudentRecord>();
while(input.hasNext()) {
id=input.nextInt();
last=input.next();
first=input.next();
year=input.nextInt();
StudentRecord record = new StudentRecord(id, last, first, year);
studentRecords.add(record);
System.out.println(id + " " + last + " " + first + " " + year + "\n");
}
System.out.println(" You have successfully read and printed from the file!");
for (StudentRecord s : studentRecords) {
System.out.println(s.toString());
}
Query query = new Query(studentRecords); // we've moved this out of AskUser method to here
// now we call the AskUser method and pass it this query object we just
// created so it can have access to it, meaning inside the AskUser method we can
// say things like 'query.getYear(2014);'
AskUser(query);
}
}

Using a method to sort a Singly Linked List in Java

Implementing a Linked List, store up to 10 names, ordered in first in First Out. Then implement two methods, one of which to sort it alphabetically by last names. This is where I am having some trouble. Here is what I tried:
Recursion. The method calls two nodes, compare them, swap if needed and then calls itself. Doesn't work with odd number of names and tends to be full bugs.
Collection but I don't know enough about it to use it effectively.
Sorting algorithms (ex. bubble sort): I can go though the list but have a hard time getting the nodes to swap.
My question is: What is the easiest way to do this?
public class List
{
public class Link
{
public String firstName;
public String middleName;
public String lastName;
public Link next = null;
Link(String f, String m, String l)
{
firstName = f;
middleName = m;
lastName = l;
}
}
private Link first_;
private Link last_;
List()
{
first_ = null;
last_ = null;
}
public boolean isEmpty()
{
return first_ == null;
}
public void insertFront(String f, String m, String l)
{
Link name = new Link(f, m, l);
if (first_ == null)
{
first_ = name;
last_ = name;
}
else
{
last_.next = name;
last_ = last_.next;
}
}
public String removeFront()
{
String f = first_.firstName;
String m = first_.middleName;
String l = first_.lastName;
first_ = first_.next;
return f + " " + m + " " + l;
}
public String findMiddle(String f, String l)
{
Link current = first_;
while (current != null && current.firstName.compareTo(f) != 0 && current.lastName.compareTo(l) != 0)
{
current = current.next;
}
if (current == null)
{
return "Not in list";
}
return "That person's middle name is " + current.middleName;
}
}
public class NamesOfFriends
{
public static void main(String[] args)
{
List listOfnames = new List();
Scanner in = new Scanner(System.in);
for(int i = 0; i < 3; i++)
{
if(i == 0)
{
System.out.println("Please enter the first, middle and last name?");
listOfnames.insertFront(in.next(), in.next(),in.next());
}
else
{
System.out.println("Please enter the next first, middle and last name");
listOfnames.insertFront(in.next(), in.next(),in.next());
}
}
System.out.println("To find the middle name, please enter the first and last name of the person.");
System.out.println(listOfnames.findMiddle(in.next(),in.next()));
}
}
Edit
After working on it a bit, I figured out how to go about sorting it. For that purpose, I am trying to implement a remove method that can remove a node anywhere on the list. While it does compile, it doesn't do anything when I run the program.
public Link remove(String lastName)
{
Link current_ = first_;
Link prior_ = null;
Link temp_ = null;
while (current_ != null && current_.lastName.compareTo(lastName) != 0)
{
prior_ = current_;
current_ = current_.next;
}
if (current_ != null)
{
if (current_ == last_)
{
temp_ = last_;
last_ = prior_;
}
else if (prior_ == null)
{
temp_ = first_;
first_ = first_.next;
}
}
else
{
temp_ = current_;
prior_.next = current_.next;
}
return temp_;
}
2: Collections is the easiest, but it seems to be not allowed in your homework
3: BubbleSort is easy but the worst known sorting algo, however for your homework it probably is ok
1: This is the same as bubble sort, but is prefered to be done without recursion
In BubbleSort you loop through your elements again and again till no swaps are neeeded anymore, then you are ready.
Collection is the easiest way to accomplish this.
Implement Comparable
Override hashcode and equals
Collection.sort()
You already has the linked list implemented, that is good.
Have you considered implementing MergeSort as the sorting algorithm? Being the divide&conquer algorithm, you will always end up with only two elements to form a list with.
The merge part is going to be trickier, but also easy. Basically you just create a new list and start filling it up with elements you get by comparing the first values of the two merging sets.
So for instance if you have two sets to merge:
[A]->[C]->[D]
[B]->[E]->[F]
the mergin process will go:
[A]
[C]->[D]
[B]->[E]->[F]
[A]->[B]
[C]->[D]
[E]->[F]
[A]->[B]->[C]
[D]
[E]->[F]
[A]->[B]->[C]->[D]
[E]->[F]
[A]->[B]->[C]->[D]->[E]
[F]
[A]->[B]->[C]->[D]->[E]->[F]

Categories