Comparing an inputted string to multiple strings efficiently - java

I'm new to Java, and I can't seem to find exactly what I'm looking for on this website. Apologies if it has already been answered in the past!
Essentially, I'm trying to compare a user inputted string to multiple strings pre-established in the program as a "database".
As an example
System.out.println("Enter a name to check the database");
Scanner names= new Scanner(System.in);
String nameinput= names.next();
if(!nameinput.equals( *[ database]?* )
System.out.println("There is no such name, you cannot continue");
How do I check if the inputted string is not equal to the entire database individually?
I have the database set up simply as
class database
{String name, name, name, name... etc.}
I'm trying to stick to keeping things simple and using the database, if at all possible.

I understood that you have a class that contains individual names as fields. It seems like you are looking for a simple collection instead:
List<String> database = Arrays.asList("item1", "item2", "item3");
System.out.println("Enter a name to check the database");
Scanner scanner = new Scanner(System.in);
String input = scanner.next();
if (database.contains(input)) {
System.err.println("There is no such name, you cannot continue");
}
Arrays.asList simply initializes the collection with the 3 items. You can later dynamically add or remove items with database.add or database.remove.
I suggest reading about Java collections and their usage

I suggest to make a list of all the names available in the database. So database class will have a method like
public List getData ()
It will return all the available names. To make the comparison easier, you can try to have the names in the list as uppercase or lowercase using .toUpperCase() or .toLowerCase()
So when you get the input string from user, convert that string to uppercase or lowercase based on your data.
Then simply you can check if this input string is part of list using contains method.
something like,
if(!availableNames.contains(inputName))
System.out.println("There is no such name, you cannot continue");

Related

Why is .binary search returning random negative values even though it worked before

I've been writing this program that reads in from a text file consisting of names and phone numbers. I created 2 arraylists both containing Item objects. names array list contains Item object haveing names as the key value and phone numbers as the value value. While the numbers array list is the opposite having the key value being phone numbers and the value value names.
Here is the code:
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Test
{
public static void main(String[] args) throws FileNotFoundException
{
File inputFile = new File("directory.txt");
ArrayList<Item> names = new ArrayList<Item>();
ArrayList<Item> numbers = new ArrayList<Item>();
Scanner in1 = new Scanner(inputFile);
while(in1.hasNextLine())
{
String name = in1.nextLine();
String num = in1.nextLine();
Item item = new Item(name , num);
names.add(item);
}
Scanner in2 = new Scanner(inputFile);
while(in2.hasNextLine())
{
String name = in2.nextLine();
String num = in2.nextLine();
Item item = new Item(num, name);
numbers.add(item);
}
Collections.sort(names);
Collections.sort(numbers);
Scanner in = new Scanner(System.in);
System.out.println("Enter number: ");
String num = in.next();
int index = Collections.binarySearch(numbers, new Item(num, null));
System.out.println(index);
System.out.println(numbers.get(index).getValue());
System.out.println("Enter name: ");
num = in.next();
index = Collections.binarySearch(names, new Item(num, null));
System.out.println(index);
System.out.println(names.get(index).getValue());
}
}
public class Item implements Comparable<Item>
{
public Item(String k, String v)
{
key = k;
value = v;
}
public String getKey()
{
return key;
}
public String getValue()
{
return value;
}
public int compareTo(Item otherObject)
{
Item other = (Item) otherObject;
return key.compareTo(other.key);
}
private String key;
private String value;
}
When testing entering the phone number it outputs the correct name and since it .binarysearch got the correct index but when entering a name outputs a random negative index value and I have no clue why.
[Here is how the console looks like][1]
[1]: https://i.stack.imgur.com/rrVEk.png
Sorry if this post is not so good. This is my first post and I really need help. Can't figure this out
In the part where you enter a number, you then search by a number.
In the second part where you enter a name, you search for a number. That will not find a name.
Your Item class only compares numbers (you call them key and value rather than number and name, it will be clearer if you fix that). You might want two classes (e.g. NumberItem and NameItem), one which compares by number, the other which compares by name (make them inherit from Item, which doesn't implement Comparable).
Another strategy is to use the existing tools, and store each type of Item in a Map, one indexed by number, the other by name. The internal implementation will probably be more efficient than what you come up with.
By using IntelliJ and a debugger I was able to discover the issue:
num = in.next();
If you debug right after and you look at num value, you will see it will be: Smith,
Seems that the whitespace is the problem here😅
Let's find out why:
If we take a look at Scanner.next() documentation:
Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext returned true.
This means that the scanner will take only the text until it encounters the delimiter. Who is the delimiter? It should be a default one if you didn't provide it, right? Let's take a look again in Scanner class and search for the default delimiter.
Right at the top of the class the documentation states:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.
So, the whitespace cuts your input from the keyboard.
Bonus some easy tips & tricks that will help you:
Name the variables simple and easy to understand. Check out some guides on naming best practices(especially in Java) and naming conventions in Java.
Use the debugger.
When your code is not doing what you think it should and you are using "3rd party classes", try to look at what and how are they doing the things under the hood. It is enough in most of the cases just to read their documentation(and IDEs like IntelliJ facilitate this by just holding ctrl and pressing click on the method name, it will point you right to the implementation where you can see the method's documentation).

Insert ArrayList into While-condition?

I have a program where the user will have the opportunity to choose from multiple strings in order to proceed:
System.out.println("\n\tWelcome! Please choose a song!");
String songChoice = scan.nextLine();
A While-loop is following this code, catching all the inputs that aren't matching the conditions.
while(!songChoice.equals("Stay") || (!songChoice.equals("Hello")) || (!songChoice.equals("Solitude"))
And so on.
I have about fifteen different songs to choose from, and I'm wondering if it's possible to insert an ArrayList in the while-condition instead of writing 15 different conditions for each and one of the strings? Something like...
while(!songChoice.equals(songs)
I've tried around but I can't get it to work... hope someone out there can help me with this!
Please follow the guidelines for a minimum runnable code snippet. Your scanner variable (scan) is not declared and that makes us have assumptions about the way the code works.
A possible solution is to create an ArrayList, populate it with all the strings and check if the input matches one of those strings.
List<String> songList = new ArrayList<>();
songList.add("Some song"); //Repeat until satisfied
System.out.println("\n\tWelcome! Please choose a song!");
String songChoice = scan.nextLine();
while (!songList.contains(songChoice)) {
//Do stuff when input is not a recognised song
}
I heavily recommend checking the javadocs of ArrayList (or any class you struggle with) for any suitable methods/fields. You already found ArrayList, why did you not understand what it does and how to use it?
Use an ArrayList to store songs :
ArrayList<String> availableSongs = Arrays.asList("Hello", "Stay", "Solitude", "Gratitude");
Scanner scan = new Scanner(System.in);
System.out.println("\n\tWelcome! Please choose a song!");
boolean validSongChoosen;
while(!validSongChoosen) {
String songChoice = scan.nextLine();
if(availableSongs.contains(songChoice)) {
validSongChoosen = true;
} else {
System.out.println("\n\tThe song you have choosen is not available");
}
}
Small improvement
Instead of using ArrayList you can use a Set as others also advised. A Set have the particularity to contains only unique non repetitive elements.
This is the cas for your songs. You can't normally have two songs with same name!
So just change your ArrayList with a HashSet

Java : Reading CSV to Linked List (with a twist)

I am a newbie to programming and was learning Java myself from Core Java .
The book mentioned a few lines about reading csv files in Java and storing its contents into a data-structure .
So while trawling the internet , I came across the following problem :
There is a school which has the following actors : Faculty , Staff and Students
Faculty has the following attributes : Name , Phone Number , E-Mail ID Address , Department , No. of Research Papers
Students has the following attributes : Name , Phone Number , E-Mail ID , Address , Roll No. , GPA
Staff has the following attributes : Name , Phone Number , E-Mail ID , Address , Department , Salary
Now , the all this data is stored in a single csv file in the following manner :
Student,Harry Potter,9999999,hp#hogwarts.magic,Hogsmeade Street,1,4.0
Staff,Argus Filch,888888,arg#mrsnorris.com,Hogwarts,Cleaning,5000
Faculty,Snape,555555,snape#snivellus.com,Hogwarts,Potions,40000
.
.
.
.
Now , I need to read the data from the cs file , in Java , and store it into a linked list such in the following order : Faculty Records followed by Staff Records followed by Student Records
My Code :
The code that I have written till now is :
import java.io.*;
import java.util.*;
public class readCSV {
public static void main(String[] args) throws FileNotFoundException
{
Scanner scanner = new Scanner(new File("CSV.csv"));
scanner.useDelimiter(",");
while (scanner.hasNext())
{
// Read the tokens and store them into a Linked List
}
scanner.close();
}
}
My Problem :
Can someone help me out ? I do not want to use any library to parse the csv and also want to make my own linked list from scratch -- it will be a good practice
My main problem is to read from csv and store the data into a linked list . An illustrative code snippet would go a long way
Disclaimer: This is not a homework question . I am self-learning Java
For linked lists I'd suggest reading one of Robert Sedgewick's Algorithm books. (Implementing a linked list itself is not going to be too hard if a) you know some Java and b) you know how linked lists work.) I expect there are plenty of example on the web, too.
Having written your own linked list implementation (for learning): throw it away and don't use it in real programs. Seriously. The existing library implementations are going to be way better; writing real-world collections libraries is a serious undertaking.
Parsing CSV is more complicated than is sounds if your data (text) can contain commas and quotes that are not CSV delimiters (which is usually true in real data).
However a naive implementation might be:
Open the file using a LineNumberReader.
Call readLine() in a loop until you get back null (no more lines).
Split each line read with line.split(",").
Process each line's fields.
You can parse the file with something like this:
Scanner scanner = new Scanner(new File("CSV.csv"));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.isEmpty()) {
continue;
}
String[] parts = line.split(",");
String name = parts[1];
String number = parts[2];
String email = parts[3];
String address = parts[4];
switch (parts[0]) {
case "Faculty":
String department = parts[5];
String papers = parts[6];
// add to list
break;
case "Student":
String roll = parts[5];
String gpa = parts[6];
// add to list
break;
case "Staff":
String department = parts[5];
String salary = parts[6];
// add to list
break;
}
}

Not able to use Scanner String input in other class

I am working on a program that has two classes. Class 1 contains a constructor called "Probability" that takes three inputs: a String and two doubles. This code is shown below:
public Probability(String inputString, double inputDouble1, double inputDouble2) {
this.inputString = inputString;
this.inputDouble1 = inputDouble1;
this.inputDouble2 = inputDouble2;
}
There is also a modifier that has five conditionals depending on the String that is fed in (i.e. if this.inputString == "String1"...), with a catch for invalid inputs. Class 2 calls the "Probability" constructor multiple times to create probabilities I need for my program.
So here's my dilemma. There are five String inputs that I need to be able to enter based on whatever I'm doing. Before, I was going into my Class 2 code and changing all of the references to this String manually (the references were "String1", "String2", etc...). In other words, the code looked something like this:
Probability P1 = new Probability("String1", double1, double2);
This is obviously a pain when you have twenty references. So I wanted to use a Scanner to take user input in order to change all of the references at once when I run my Main. The user would enter String1 when prompted, and then the input would be set equal to a String variable. This is my new code, where double1 and double2 are previous Scanner user inputs:
Scanner scan = new Scanner(System.in);
System.out.print("Please enter a string: ");
String userInput = scan.nextLine();
Probability P1 = new Probability(userInput, double1, double2);
But this doesn't work. I get the error that I've set up in my catch in the Class 1 modifier that says the input doesn't match any of the strings in the conditionals. I have tried the inputs String1 and "String1". Does anyone have any ideas why this may be? I have no issues with the double inputs fed from Class 2 into the Class 1 modifier.
Yes my friend as other suggest you have to compare the two string using equals method not by using == operator which is for reference matching not content matching.

java : Make it the best "Searching method"

I have design the search method. According to my requirement, If a user wants to search a customer’s record, he/she can input the customer’s family name or given name into the name text field and then click the search button. The following two screen shots show an example of the events before and after button click (with input the name to be searched is Lee)
And below is the code for searching. It is working fine but I want to make it better?
private void search()
{
String studentName=CNameTextField.getText();
String record="";
int count=0;
for(int i=0; i<myList.size();i++)
{
String name=myList.get(i).getName();
String [] splitName= name.split(" ");
if(studentName.equals(splitName[0]) || studentName.equals(splitName[1]))
{
count++;
record=record+"\n"+myList.get(i).toString();
}
display.setText("");
display.append(count + " result(s) found for "+ studentName);
display.append("\n "+ record);
}
}
So you've basically got a list of String items, and you're searching through all of them for the value?
My recommendation would be to create Objects for each line in your DisplayArea, rather than Strings. For example, when you read in the input file for your DisplayArea, do the split() for each line and create objects of type Customer that have fields called ID, name, room, etc. This would be better OO programming anyway - Strings don't really have any meaning, whereas a Customer has meaning.
If you do this, in the search you can simply loop over all the Customers in the list, asking whether the name.equals(customer.getName()); This would remove the need to split the line every time you search.

Categories