patternjavaMinor
Processing names and meanings from .txt files
Viewed 0 times
frommeaningsnamesfilesandprocessingtxt
Problem
I wrote this program to process the names and meanings from .txt files. From the
Also, for this program my instructor only allows us to use Scanners, while and if/else loops, boolean and file input to solve this problem.
Here are samples for
Jax M 0 0 0 0 0 0 0 0 0 0 0 0 347
Randall M 974 620 650 467 369 232 70 59 100 136 192 440 841
Minnie F 8 22 50 87 122 168 258 516 995 0 0 0 0
Brianna F 0 0 0 0 0 0 0 0 0 340 61 15 30
MUBINA f Arabic Feminine form of MUBIN
ANDRONIKOS m Ancient Greek Means "victory of a man" from Greek
(andros) "of a man" and (nike) "victory".
SALVATORE m Italian Italian cognate of SALVADOR
And here is my code:
```
import java.io.*;
import java.util.*;
public class BabyNames {
public static void main(String[] args) throws FileNotFoundException {
Scanner inputName = new Scanner(new File("names.txt"));
Scanner inputMeanings = new Scanner(new File("meanings.txt"));
Scanner console = new Scanner(System.in);
intro();
System.out.print("Name: ");
String nameIn = console.next();
System.out.print("Gender (M or F): ");
String genderIn = console.next();
nameAndMeaning(inputName, inputMeanings, nameIn, genderIn);
}
public static void intro() {
System.out.println("This program allows you to search through the");
System.out.println("data from the Social Security Administration");
System.out.println("to see how popular a particular name has been");
System.out.println("since 1890.");
System.out.println();
}
public static void nameAndMeaning(Scanner inputName, Scanner inputMeanings, String nameIn, String genderIn) {
boolean hasLine = false;
while(inputName.hasNextLine()) {
S
while loops I wrote, I noticed they are very similar loops containing Scanners. I am wondering if there is any way to reduce the redundancy in the code.Also, for this program my instructor only allows us to use Scanners, while and if/else loops, boolean and file input to solve this problem.
Here are samples for
names.txt and meanings.txt:names.txtJax M 0 0 0 0 0 0 0 0 0 0 0 0 347
Randall M 974 620 650 467 369 232 70 59 100 136 192 440 841
Minnie F 8 22 50 87 122 168 258 516 995 0 0 0 0
Brianna F 0 0 0 0 0 0 0 0 0 340 61 15 30
meanings.txtMUBINA f Arabic Feminine form of MUBIN
ANDRONIKOS m Ancient Greek Means "victory of a man" from Greek
(andros) "of a man" and (nike) "victory".
SALVATORE m Italian Italian cognate of SALVADOR
And here is my code:
```
import java.io.*;
import java.util.*;
public class BabyNames {
public static void main(String[] args) throws FileNotFoundException {
Scanner inputName = new Scanner(new File("names.txt"));
Scanner inputMeanings = new Scanner(new File("meanings.txt"));
Scanner console = new Scanner(System.in);
intro();
System.out.print("Name: ");
String nameIn = console.next();
System.out.print("Gender (M or F): ");
String genderIn = console.next();
nameAndMeaning(inputName, inputMeanings, nameIn, genderIn);
}
public static void intro() {
System.out.println("This program allows you to search through the");
System.out.println("data from the Social Security Administration");
System.out.println("to see how popular a particular name has been");
System.out.println("since 1890.");
System.out.println();
}
public static void nameAndMeaning(Scanner inputName, Scanner inputMeanings, String nameIn, String genderIn) {
boolean hasLine = false;
while(inputName.hasNextLine()) {
S
Solution
I would start from the declaration of
I would also recommend reading everything from the files at once and use that
Furthermore, you don't have to call
The rest is just a search function to find the
The time complexity of searching a value from a
You also have a lot of duplicate code in the two
Solving with Constraints
Given the constraints for the solution, I'd solve it as below
Please note that
Now if you'll be very strict and won't accept the use of a
main. You are throwing an exception from it but no other class will handle it. You should put your Scanners inside a try-catch and handle the exception properly. I would also recommend reading everything from the files at once and use that
collection of data in your code logic. A Scanner locks the file until it's finished with it.Furthermore, you don't have to call
System.out.println(...) just for the sake printing a new line. Use the \n escape sequence for doing the sameSystem.out.println("This program allows you to search through the \ndata from the Social Security Administration \nto see how popular a particular name has been \nsince 1890.\n");The rest is just a search function to find the
meaning based on the name and gender. I recommend creating a name Baby class with name and gender attributes and use a Hashtable to search for the meaning. The class can be as simple asclass Baby{
private String name;
public String Name(){
return name;
}
private boolean gender;
public boolean Gender(){
return gender;
}
public Baby(String name, boolean gender){
this.name = name;
this.gender = gender;
}
}The time complexity of searching a value from a
Hashtable is close to O(1) while a typical looping mechanism is O(n). The speed becomes n times slower as the size of the collection increases.You also have a lot of duplicate code in the two
while statements. To resolve that I'd recommend extracting out the if-else logic outside and calling a common function with a single loop. Something likebool foundMatch = findMatch(...);
if(foundMatch) {
findMatch(...) // with different params now
}
else {
// print error message
}Solving with Constraints
Given the constraints for the solution, I'd solve it as below
public static void main(String[] args){
Scanner consoleInput = new Scanner(System.in);
// Welcome message
System.out.println("This program allows you to search through the \ndata from the Social Security Administration \nto see how popular a particular name has been \nsince 1890.\n");
// Receive user input
System.out.print("Name: ");
String inputName = consoleInput.next();
System.out.print("Gender: ");
String inputGender = consoleInput.next();
consoleInput.close(); // Closed as not needed anymore
try (Scanner namesScanner = new Scanner(new File("names.txt"));
Scanner meaningsScanner = new Scanner(new File("meanings.txt"))) {
String foundMatch = findMatch(inputName, inputGender, namesScanner);
if(!foundMatch.equals("")){
System.out.println(foundMatch);
System.out.println(findMatch(inputName, inputGender, meaningsScanner));
} else{
System.out.println("\""+ inputName + "\" not found.");
}
} catch (FileNotFoundException ex){
System.out.println("File Not Found");
}
}
private static String findMatch(String name, String gender, Scanner fileScanner){
while(fileScanner.hasNextLine()){
String currentLine = fileScanner.nextLine();
// Split it to a String array and check the first two values
String contents[] = currentLine.split(" ");
if(name.equalsIgnoreCase(contents[0]) && gender.equalsIgnoreCase(contents[1])){
return currentLine;
}
}
// if no returns occured till the end of the file
return "";
}Please note that
- The
Scannersshould be closed once you're done using them. UsingTry-with-resourcesstatement is a better alernative (as recommended in the comments). You don't have to worry about theScannersbeing closed. Thetryblock functions like ausingfrom C# and releases all resources after the block itself is finished. The defined resources must implement thejava.io.Closeableinterface for this functionality and the Java project must use Java SE 7 or above.
- Both name matching operations can be handled by the same function. The significance of positive matches is handled by the calling function. This also enforces Single Responsibility Principle (SRP) and improves code maintainability
- Use
equalsIgnoreCase(...)instead ofequals()to avoid usingtoLowerCase()on all strings
returnis called immediately from the function on the first match to avoid redundant checks
Now if you'll be very strict and won't accept the use of a
String array. You can replace it by extracting the first and second values using substring(...) function on the first two whitespacesCode Snippets
System.out.println("This program allows you to search through the \ndata from the Social Security Administration \nto see how popular a particular name has been \nsince 1890.\n");class Baby{
private String name;
public String Name(){
return name;
}
private boolean gender;
public boolean Gender(){
return gender;
}
public Baby(String name, boolean gender){
this.name = name;
this.gender = gender;
}
}bool foundMatch = findMatch(...);
if(foundMatch) {
findMatch(...) // with different params now
}
else {
// print error message
}public static void main(String[] args){
Scanner consoleInput = new Scanner(System.in);
// Welcome message
System.out.println("This program allows you to search through the \ndata from the Social Security Administration \nto see how popular a particular name has been \nsince 1890.\n");
// Receive user input
System.out.print("Name: ");
String inputName = consoleInput.next();
System.out.print("Gender: ");
String inputGender = consoleInput.next();
consoleInput.close(); // Closed as not needed anymore
try (Scanner namesScanner = new Scanner(new File("names.txt"));
Scanner meaningsScanner = new Scanner(new File("meanings.txt"))) {
String foundMatch = findMatch(inputName, inputGender, namesScanner);
if(!foundMatch.equals("")){
System.out.println(foundMatch);
System.out.println(findMatch(inputName, inputGender, meaningsScanner));
} else{
System.out.println("\""+ inputName + "\" not found.");
}
} catch (FileNotFoundException ex){
System.out.println("File Not Found");
}
}
private static String findMatch(String name, String gender, Scanner fileScanner){
while(fileScanner.hasNextLine()){
String currentLine = fileScanner.nextLine();
// Split it to a String array and check the first two values
String contents[] = currentLine.split(" ");
if(name.equalsIgnoreCase(contents[0]) && gender.equalsIgnoreCase(contents[1])){
return currentLine;
}
}
// if no returns occured till the end of the file
return "";
}Context
StackExchange Code Review Q#128546, answer score: 3
Revisions (0)
No revisions yet.