I have the following method in a program of mine that allows a user to enter a unique ID that is associated with a laptop in an ArrayList.
The desired output is as follows:
If the ID entered by the user matches an ID in the ArrayList, the laptop and its specifications will print out.
If the ID does not match, it will print out "Invalid ID".
I am very close to achieving this; however I can only figure out how to get it to print whether or not it matches for each laptop in the list. So for example, if the ID entered by the user matches one of three laptops in the list it will print as follows:
Acer Predator Helios 300 CPU: Intel i7-9750h GPU: NVIDIA GTX1660ti Memory: 16GB ID: 1234567
Invalid ID.
Invalid ID.
So my question is: how do I get it to print ONLY the single match or "Invalid ID" while still being able to loop through the entire list to check for a match? Not necessarily asking you to spoon feed me the fix, but at least help point me in the right direction or help with the logic. I thank you in advance for any help!
My method is as follows:
private static void findLaptop(ArrayList arr) {
//Prompt user to input an ID.
System.out.println("Input ID: ");
System.out.println();
//Scan for user input.
Scanner keyboard = new Scanner(System.in);
int inputId = keyboard.nextInt();
//Loop through ArrayList and check for a match.
for(int i=0; i<arr.size(); i++) {
//If entered ID matches, print laptop information.
if(inputId == ((Laptops) arr.get(i)).getId()) {
System.out.println(((Laptops)arr.get(i)).getModel() + " CPU: " + ((Laptops)arr.get(i)).getCpu() + " GPU: " +
((Laptops)arr.get(i)).getGpu() + " Memory: " + ((Laptops)arr.get(i)).getMemory() + "GB ID: " +
((Laptops)arr.get(i)).getId());
}
//If entered ID does not match, print invalid ID.
else if(inputId != ((Laptops) arr.get(i)).getId()) {
System.out.println("Invalid ID.");
}
}
}
Use below code:
//Create a boolean
boolean found= false;
for(int i=0; i<arr.size(); i++) {
//If entered ID matches, print laptop information.
if(inputId == ((Laptops) arr.get(i)).getId()) {
System.out.println(((Laptops)arr.get(i)).getModel() + " CPU: " + ((Laptops)arr.get(i)).getCpu() + " GPU: " +
((Laptops)arr.get(i)).getGpu() + " Memory: " + ((Laptops)arr.get(i)).getMemory() + "GB ID: " +
((Laptops)arr.get(i)).getId());
//set boolean true and break
found = true;
break;
}
}
//Out side the look check If entered ID does not match, print invalid ID.
if(!found) {
System.out.println("Invalid ID.");
}
You can do this using a return statement that is used after printing a match
for(int i=0; i<arr.size(); i++) {
//If entered ID matches, print laptop information.
if(inputId == (arr.get(i)).getId()) {
System.out.println((arr.get(i)).getModel() + " CPU: " + (arr.get(i)).getCpu() + " GPU: " +
(arr.get(i)).getGpu() + " Memory: " + (arr.get(i)).getMemory() + "GB ID: " +
(arr.get(i)).getId());
return;
}
}
// outside loop
System.out.println("Invalid ID.");
edit
If you have you ArrayList set up properly as ArrayList<Laptop> then you would not need all those crazy casts.
edit2
If you a foreach loop it would be even cleaner
for (Laptop lt : arr) {
if (iputId == lt.getId()) // etc
Supposing you have a class called Laptop as follows:
public class Laptop {
private String id;
private String manufacturer;
// other fields
// getters and setters
}
You can find matches with an id using Java 8 Streams:
List<Laptop> laptops = ...
String idToSearch = "something";
Optional<Laptop> result = laptops.stream() // convert into stream for easier handling
.filter(l -> l.getId().equals(idToSearch)) // find only laptops with a matching id
.findFirst(); // find the first one, if present
The variable result is an Optional<Laptop>, meaning it may or may not contain a Laptop value. You can consume this result as follows:
Laptop laptop = result.get(); // throws an exception if no value present, not reccomended
Laptop laptop = result.orElse(null); // returns null if no value present
result.ifPresent(laptop -> {
doSomething(laptop); // this function is only called if a value is present
})
Related
I'm working on little "project" for saving some data in a Hashmap which I want to print out later in my console.
I've almost finished with the whole code but I'm having problems with giving it out in my console...
My code so far is:
import java.util.HashMap;
import java.util.Scanner;
public class Passwordsaver` {
public static void main(String[] args) throws InterruptedException {
// declare the hashmap
HashMap<Integer, String> Password = new HashMap<>();
boolean loopAgain = true;
Scanner scan = new Scanner(System.in);
// loop while user not entering no
do {
// ask for account (page)
System.out.print("Enter Page:");
String page = scan.nextLine();
// ask for password
System.out.print("Enter Password");
String password = scan.nextLine();
// add the key value pair from user input to the hashmap
String oldVal = password + page;
if (oldVal!=null) {
System.out.println("The password for the page: " + page + " is "
+ password + " and will be overwritten if entered again");
}
// ask user to check if another entry is required
System.out.print("Enter another account (y/n)?");
String answer = scan.nextLine();
// condition to satisfy in order to loop again
loopAgain = (answer.equals("y") || answer.equals("Y"));
} while (loopAgain);
scan.close();
System.out.println("\n**********************************");
System.out.println("The following accounts are in database");
System.out.println(" account "+ " password");
for(int page:Password.keySet()){
System.out.println(" "+ Password +" "+Password.get(page));
}
System.out.println("\n**********************************");
}
}
Everything works except the last step...How can I print it?
Is there also a possibility to save the data so at a later time I can still change the map without having Eclipse opened the whole time?
Many thanks in advance!!!
You are printing the full HashMap (Password) and not the key of every entry.
Have a look at the following loop:
for(int page:Password.keySet()){
System.out.println(" "+ page +" "+Password.get(page));
}
Here we print the key and the value of the entry.
In terms of performance, it's better to iterate over the entrySet, so you do not have the additional cost of a look up:
for(Map.Entry<Integer,String> entry:Password.entrySet()){
System.out.println(" "+ entry.getKey() +" " + entry.getValue());
}
EDIT
In addition you forgot to store the page/password combination in your hashmap. Add
Password.put(page, password) to store the data.
You also have to change the type to the HashMap to HashMap<String,String>
The following code will work:
Map<Integer, String> passwords = ...
for (Map.Entry<Integer, String> entry : passwords.entrySet()) {
// iterates over every entry in the map, creates a variable called "entry"
int key = entry.getKey();
String value = entry.getValue();
// now you can print with whatever formatting you want. e.g.:
System.out.println("account: " + key + ", password: " + password);
}
Or, using Java 8 functional style code:
passwords.forEach((key, value) -> {
System.out.println("account: " + key + ", password: " + password);
});
If you want to store the data, take a look JSONs, and the Jackson Databind library. This is a library to map Java objects to JSONs, and back (this isn't all it does, but just one of the features). In short, you can convert your Map to and from a String, so that it can be saved to a file/sent over the network/etc.
I need some help writing a program
Using this code I am able to enter in a track name, artist, etc.
I have a problem that I cannot now show this information in JOptionPane to display all of my info
import java.util.Scanner;
import javax.swing.JOptionPane;
public class TestTrack
{
public static void main(String[] args)
{
Scanner myScan = new Scanner(System.in);
System.out.println("Track name");
String name = myScan.nextLine();
System.out.println("Artist");
String Artist = myScan.nextLine();
System.out.println("Track length seconds");
String seconds = myScan.nextLine();
System.out.println("Album");
String Album = myScan.nextLine();
JOptionPane.showMessageDialog(null,"Trackinfo:")
}
}
So I guess I would want the pop out window to say
Track Name: "blank"
Artist: blank
Another question I have is how to ask this question multiple times by using "while" and asking if I would like to add another track
Sorry if I am using any terminology incorrectly I just started to learn Java
This line: JOptionPane.showMessageDialog(null,"Trackinfo:")
Contains what the pop-up window will contain. You pass in what you want its contents to be as the 2nd parameter, which is currently "Trackinfo".
To incorporate a while loop, you'll have to have a loop control variable, or a condition that will break the loop. In my example I used a string. My example uses a while loop that will continue as long as the string is not equal to "quit".
String test = "";
while( ! test.equals("quit") ) {
//use Scanner to get the next value the user enters
//ask for track info
//display that info in a message box
}
To obtain this:
Note: the texts of the OK and Cancel buttons are localized, if your computer is set to US locale you doesn't see 'Annuler"... ;-)
code this:
int answer = 0;
do {
/*----------------------------------------------------------------------------
Here you put the code which set the variables name, artist, seconds... (1)
----------------------------------------------------------------------------*/
final String title = "Track info";
final String message =
"<html><table>" +
"<tr><td>Track name" + "</td><td>" + name + "</td></tr>" +
"<tr><td>Artist" + "</td><td>" + artist + "</td></tr>" +
"<tr><td>Track length seconds</td><td>" + seconds + "</td></tr>" +
"<tr><td>Album" + "</td><td>" + album + "</td></tr>" +
"</table>";
answer =
JOptionPane.showConfirmDialog(
null, message, title, JOptionPane.OK_CANCEL_OPTION );
} while( answer == JOptionPane.OK_OPTION );
(1) You may choose Scanner or GUI whith JOptionPane.showInputDialog()
JOptionPane.showMessageDialog(null,"Trackinfo:" + "\nArtist: " + Artist + "\nseconds: " + seconds + "\nAlbum: " + Album)
Each '\n' means a new line. for doing this multiple times, you should place your code in a while loop, something like this:
while(!(Artist == "end")) {
//your code
}
Use myScan.next() instead of myScan.nextLine()
To output the information into the Message Dialog, use
String trackInfo = "Track Name: " + name + " | Artist : " +artist+ " | Track Length: " + seconds + " | Album: " + album;
JOptionPane.showMessageDialog(null, trackInfo, "Trackinfo", JOptionPane.INFORMATION_MESSAGE);
Problem solved.
I have two methods in my class.
private void retrieveDetails(){
List<String> details = File.getCredentials();
username = details.get(0);
pw = details.get(1);
}
private void checkCredentials() throws IOException {
retrieveDetails();
System.out.println("\nPlease enter USERNAME: ");
String usersName = scan.next();
System.out.println("\nPlease enter PASSWORD: ");
String usersPW = scan.next();
System.out.println("\nEntered details: " + usersName + ", " + usersPW);
System.out.println("\nSystems details: " + userName + ", " + pw);
if (usersName.equals(username) && usersPW.equals(pw)) {
doWork();
} else {
System.out.println("Incorrect credentials");
}
}
I thought I came up with a solution by moving the following up to where my strings are initialized.
List<String> creds = File.getCredentials();
I created a System.out statement to check if the details coming from retrieveDetails() match those entered by the users. They do match - but when the system goes to the else clause instead of executing doWork();
If what is printed is the same then try trimming before comparing. E.g.:
if (usersName.trim().equals(username.trim()) && usersPW.trim().equals(pw.trim())) {
When i have similar problem i do this simple trick:
Print the size of the strings you are comparing because sometimes you have characters like \n or \r which are not visible when you print the string.
First of all, it seems like you have a typo in sysout statement below.
System.out.println("\nEntered details: " + usersName + ", " + usersPW);
System.out.println("\nSystems details: " + userName + ", " + pw); //Should be username
Secondly, you might wanna trim the strings for better string comparison.
Sometimes strings read from file or console can contain unwanted and hard-to-catch empty strings like spaces and tabs. These can be removed by calling .trim() method on strings.
Thus, try using the following code instead:
if (usersName.trim().equals(username.trim()) && usersPW.trim().equals(pw.trim())) {
}
usersName.equals(username) && usersPW.equals(pw).
I have faced these problem also, These kind of equality always tricky, Try to trim the strings that you are going to compare, as well as if you can compare these strings based on their length.
if (usersName.trim().equalsIgnoreCase(username.trim()) && usersPW.trim().equalsIgnoreCase(pw.trim()))
or
if (usersName.trim().length()==username.trim().length && usersPW.trim().length()==pw.trim().length))
In the program I'm creating, the user will input values to create an array of videos. Each video contains several data fields (number, title, publisher, duration & date). However what I am currently trying to acheive is to let the user choose a particular video in the array they just created, select the data field they wish to rename, rename the value and then set the renamed value as the new value. Here is my code for adding videos to an array:
public Library createLibrary()
{
Library video = new Library();
java.util.Scanner scannerObject =new java.util.Scanner(System.in);
for (int i = 0; i < videos.length; i++)
{
//User enters values into set methods within the Library class
System.out.print("Enter video number: " + (i+1) + "\n");
String number = scannerObject.nextLine();
System.out.print("Enter video title: " + (i+1) + "\n");
String title = scannerObject.nextLine();
System.out.print("Enter video publisher: " + (i+1) + "\n");
String publisher = scannerObject.nextLine();
System.out.print("Enter video duration: " + (i+1) + "\n");
String duration = scannerObject.nextLine();
System.out.print("Enter video date: " + (i+1) + "\n");
String date= scannerObject.nextLine();
System.out.print("VIDEO " + (i+1) + " ENTRY ADDED " + "\n \n");
//Initialize arrays
videos[i] = new Library ();
videos[i].setVideo( number, title, publisher, duration, date );
}
return video;
}
And here is the basic concept for my select and replace function for those who can't figure out what I mean:
public void replaceVideo(Library[] videos, String replaceTo, String replaceWith)
{
for (int i = 0; i < videos.length; i++)
if (videos[i].equals(replaceTo)) {
videos[i]= replaceWith;
}
}
Simpler solutions will be appreciated. Thanks.
Try comparing replaceTo to the name of the video (or whatever replaceTo is supposed to match):
if (videos[i].getName().equals(replaceTo)) {
I can't see your replace ever working, since it appears that you are comparing a Library type and a String type with .equals().
If you use one of the Collection classes instead of an array, the replace method changes to
public void replaceVideo(Vector<Library> videos, Library current, Library newCopy)
{
Collections.replaceAll(videos, current, newCopy);
}
I used Vector, but you could use a Set, List, etc. as needed.
For your code to work, you need to override the Library.equals method to compare strings only. Otherwise, you can compare the video title, for one sample, against the parameter replaceTo.
Certainly, it is OOP elegant to override the equals method. Try my suggestion and Thomas'
Good luck.
Weird problem. I run this (very elementary) procedure to find a username and password in a file, and the program should compare the password entered to the password saved. Every time, however, i get a strange String index out of range: -1 exception. I've suffered a similar problem before, however this time the indexOf('.') call is returning -1; which it doesn't like. Why is indexOf() returning -1 if it causes an error? Here's the source:
public String loginToClient() throws FileNotFoundException, IOException {
//decryptUsers();
int tries;
tries = 5;
while (tries > 0) {
System.out.println("LOGIN");
String usnm = c.readLine("Username: ");
char [] passwd = c.readPassword("Password: ");
users = new FileInputStream("users.fra");
DataInputStream dis = new DataInputStream(users);
BufferedReader br = new BufferedReader(new InputStreamReader(dis));
String logindat = br.readLine();
System.out.println(logindat);
if (logindat.contains(usnm) == null) {
System.err.println("Username not recognised, please try another or create user.");
usnm = "INV";
return usnm;
}
else {
int startUsnm = logindat.indexOf(usnm);
System.out.println("startUsnm: " + startUsnm);
String logdat = logindat.substring(startUsnm, logindat.indexOf("."));
System.out.println("logdat: " + logdat);
int endUsnm = logdat.indexOf(':');
System.out.println("endUsnm: " + endUsnm);
int usnmend = endUsnm - 1;
System.out.println("usnmend: " + usnmend);
int startPass = endUsnm + 1;
System.out.println("startPass: " + startPass);
int endPass = logdat.indexOf('.');
System.out.println("endPass: " + endPass);
String Usnm = logdat.substring(0, usnmend);
System.out.println("Usnm: " + Usnm);
int passend = endPass - 1;
System.out.println("passend: " + passend);
String Pass = logdat.substring(startPass, passend);
System.out.println("Pass: " + Pass);
char [] Passwd = Pass.toCharArray();
if (usnm.equals(Usnm)) {
if (Arrays.equals(passwd,Passwd)) {
System.out.println ("Logged in. Welcome, " + usnm + ".");
String data = "LOGIN: " + usnm;
printLog(data);
//encryptUsers();
return usnm;
}
else {
System.out.println ("Incorrect password, please try again.");
String data = "PASWFAIL: " + usnm;
printLog(data);
tries -= 1;
}
}
else {
System.out.println ("Username not recognised.");
printLog("USNAMFAIL");
usnm = "INV";
return usnm;
//encrytUsers();
}
}
}
//encryptUsers();
System.exit(2);
return usnm;
}
And here's some input/output:
Startup initiated.
Logfile exists.
Users file exists.
New user? n
ELSE
LOGIN
Username: rik
Password:
rik:55.
startUsnm: 0
endUsnm: 3
startPass: 4
endPass: -1
Usnm: rik
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -5
at java.lang.String.substring(String.java:1949)
at client0_0_2.loginToClient(client0_0_2.java:103)
at client0_0_2.general(client0_0_2.java:209)
at client0_0_2.<init>(client0_0_2.java:221)
at client0_0_2.main(client0_0_2.java:228)
EDIT : SOLUTION FOUND!
For some reason, indexOf() does not want to find a '.'- when replaced with a hyphen('-'), however, it runs perfectly, seemingly!
I think the error is in this line:
String Pass = logdat.substring(startPass, passend);
For some reason (you'll have to determine why), you compute passend by searching for . in the string. If . isn't present, indexOf returns -1 as a sentinel. This isn't the line that causes the exception, though. I think it's the above line, since if you try to compute a substring ending at passend when passend is -1, you would get the above error.
Try determining why your string doesn't contain a . in it.
Hope this helps!
When indexOf() returns -1, it means that the value couldn't be found in the String. So, in this case, you're searching a String for '.' which doesn't exist in the String.
I would recommend that you always check the values of indexOf() after the call, and handle the -1 properly. For many cases, its probably sufficient to set it to either 0 or string.length(), depending on how you will use it later in your code.
Regardless, if you're expecting a '.' to exist and there isn't one, you'll need to debug through your code to find out what the value is, and where the '.' is missing.
indexOf() returns -1 if the specified string can't be found.
The problem is in the Line:
String Pass = logdat.substring(startPass, passend);
because of negative index.