This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
My customer.dat files looks like as follows:
4
Jon 1000
Jane 2000
Jake 20000
Drake 100000
The first number represents the total number of customers in that file, while the first string is the Name of the customer and the latter is the balance they have.
The following code is the application code I have written. I want it to read from the customer.dat and create an array. The problem with the application is that I created a customer ID, which checks the name the user inputs(if it exists in the array( and then sets a customer ID. However, whenever I run the application, no matter what name I type, even if I type Drake - and type "1" to view the portfolio, it ends up always showing the first name which is Jon.
Scanner infile2 = new Scanner(new File("customer.dat"));
customer[]mycustomers; // declaring an array to stock
int numofcustomers = infile2.nextInt();
mycustomers = new customer [numofcustomers];
for (int i = 0; i < numofcustomers; i++)
{
mycustomers[i] = new customer(infile2.next(),infile2.nextDouble(), numofcustomers);
System.out.println(mycustomers[i].toString());
}
Scanner input = new Scanner (System.in);
System.out.println("Please type in your name");
String Name = input.nextLine();
int cusID = 0;
for (int i = 0; i < numofcustomers; i++)
{
if ( Name == mycustomers[i].getName())
{
cusID = i;
}
}
System.out.println("Please type in 1 for a customer to view their portfolio, 2 to trade stocks or 3 to exit the application");
int choice = Integer.parseInt(input.nextLine());
if (choice == 1)
{
System.out.println(mycustomers[cusID].toString());
}
The following is a snippet of what is located in my customer.java which contains setters and getters:
public customer(String n, double b, int Size)
{
Name = n;
balance = b;
stock[] A = new stock[Size];
Portfolio = A;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
I'm not sure if I was able to describe the problem correctly, but if not, let me know if any more information is required.
First, Java naming conventions usually dictate you CamelCase class names (i.e. rename to Customer instead of customer).
I believe your problem is here:
Name == mycustomers[i].getName()
In Java, Strings are objects, and you have to use the equals() method to do a comparison, like so:
Name.equals(mycustomers[i].getName())
If you use the standard ==, the comparison is done on the object's memory location, so unless Name and getName() are literally the exact same String object (unlikely), that will be false. This means the if statement never evaluates to true, cusID remains 0 as you initialized it, and so you print out the first name in the list, Jon.
I would suggest, in addition to changing the above, that you initialize cusID to -1 so you can differentiate between a name that is not found in the list and the selection of the first element in the list. Also, what if two people by the same name are in the list? (Hint: The first one will never be selected in your current implementation.)
Related
This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 2 years ago.
I have an assignment where I have to have a class named Employee with two variables and a class called Salary that inherits those variables and declares new ones. Within the Salary class, I have to create a method that will take user input for the different variables. The first number inputted is the number of employees you are giving information for and tells the loop how many times to go around. After typing in the information for all the employees the information must be presented like this
123 John engineer 40000.0
124 Emma Testing 33000.0
The only other thing that is required in the program is a function that will check the salary variable and if it is under 20000, not display the employee information to the console.
I have the user input working but I can't seem to get the array to display properly. Whatever I try I either get gibberish or null. I have tried putting the array and the array printing function in the display method and the main method and it doesn't make a difference. How can I fix this?
Side note: I know having different scanners for each input is not the best way of doing things it's just temporary. I'm trying to get the program to work before cleaning it up. The reasoning for it is a type mismatch error using one scanner as a result of scanning an int, then two strings, then a double.
This is the code I have right now:
import java.util.Scanner;
class Employee {
int employee_id;
String employee_name;
Employee(int employee_id, String employee_name) {
}
Employee() {
}
}
class Salary extends Employee {
double monthly_salary;
String designation;
int num_of_employees;
int n = 0;
Salary(int employee_id, String employee_name, String designation, double monthly_salary) {
super(employee_id, employee_name);
}
Salary() {
}
void display() {
Scanner s = new Scanner(System.in);
Scanner c = new Scanner(System.in);
Scanner a = new Scanner(System.in);
Scanner e = new Scanner(System.in);
Scanner t = new Scanner(System.in);
num_of_employees = s.nextInt();
for (;n<num_of_employees;) {
employee_id = c.nextInt();
employee_name = a.nextLine();
designation = e.nextLine();
monthly_salary = t.nextDouble();
n++;
}
s.close();
c.close();
a.close();
e.close();
t.close();
}
}
public class Solution2 {
public static void main(String[] args) {
Salary sal = new Salary();
Salary salary[] = new Salary[10];
sal.display();
salary[sal.n] = new Salary(sal.employee_id, sal.employee_name, sal.designation,
sal.monthly_salary);
if (sal.monthly_salary >= 20000) {
System.out.println(salary[sal.n]);
}
else {
System.out.println("");
}
}
}
The result from the array with this code is
Salary#7b23ec81
So I am reading from a file with scanner it has the similar format:
title, name, age
Mr, Matthew, 20
mr, Paul, 30
miss, Anne, 24
CSV^
class person{
String name, title;
int age;
public crimeData(String csv){
String[]list = csv.split(",", -1);
name = list[0];
title = list[1];
age = list[2];
}
}
Console Program
Scanner input = new Scanner(System.in);
System.out.println("Please select what data you want to load:");
String selection = input.next();
int temp = 0;
for(int i=0; i< header.length; i++){
if(header[i].equals(selection)){
temp = i;
break;
}
}
temp will give us the index of the option specified so if it is 2 we will want to access the age property
When my console application runs I prompt them(the user) for the data that they want.
So they may enter "age" So I am lost on how I may take this "age" String and access the person object with it.
The ideal case for the program output should be: 20,30,24 going through each age and printing
I take their input so String input = scanner.nextLine();
Then I loop through my array of person objects to get the index of the input. Once I have this index I then want to access the property of person at the index. So like if my index was 1 I would want to access the property 'name'.
In javascript I could take the string and say person['age'] although java's a whole different story. I have looked into java's "reflection API" although it's a heavy learning curve.
I have looked into java's "reflection API" although it's a heavy learning curve.
Well, Reflection is the way to go. It's widely used in many frameworks.
But perhaps a simpler solution will fit your needs. Use a switch to decide which attribute to return, and encapsulate this in a method of the Person class:
class Person {
private String name, title;
private int age;
public loadData(String csv){
String[] list = csv.split(",");
name = list[0];
title = list[1];
age = Integer.parseInt(list[2]);
}
public Object attribute(String attribute) {
switch (attribute) {
case "name": return this.name;
case "title": return this.title;
case "age": return this.age;
default: throw new RuntimeException("Invalid attribute: " + attribute);
}
}
}
Encapsulating the switch inside the method is in line with OOP principles, since it hides how attributes are stored from other objects, only exposing an interface to query them. Reflection breaks all encapsulation.
Though in general I am not in favor of using Map for holding fields for an object, if the number of properties is large and could even potentially vary across CSV files (e.g., some file has the University a person attended, another does not), then using a Map to hold the properties might be appropriate.
In this case, one would define a simple Person class:
public class Person {
Map<String, String> props = new HashMap<>();
public void addProperty(String propertyName, String value) {
// could add error checking to ensure propertyName not null/emtpy
props.put(propertyName, value);
}
/**
* returns the value of the property; may return null
*/
public String getProperty(String propertyName) {
return props.get(propertyName);
}
}
If it is know that certain attributes/properties will always be loaded, then accessors such as getName() could be added:
public String getName() {
return props.get("name");
}
public int getAge() {
String age = props.get("age");
// or throw exception if missing
return (age != null ? Integer.parseInt(age) : -1);
}
Though note I would expect name to not be a single entry for most datasets, as there typically would be last name, first name, etc. Nonetheless, the pattern for a limited number of commonly expected values is the same. Also, you can adapt so that you could get integer values directly for certain well-known fields.
Then, when you parse the file, you keep the title row that has the attribute definitions. Then for each row that you subsequently read, you create a new Person object, and then add the properties in order.
List<Person> allPersons = new ArrayList<>();
while ( (line = READ_NEXT_LINE) ) {
// NOTE: this is not a safe way to handle CSV files; should really
// use a CSV reader as fields could have embedded commas
attrs[] = line.split(",");
Person p = new Person();
for (int i = 0; i < titleRow.length; ++i) {
p.addProperty(titleRow[i], attrs[i]);
}
allPersons.add(p);
}
You can then get a specific Person by Person myPerson = allPersons.get(index_of_person), and much akin to the way you would have used Javascript, you can do String val = myPerson.getProperty("age").
If you need to search by a given attribute, you can then stream/loop over the allPersons and check of equivalence based upon a given property.
// find all people of a given age
List<Person> peopleAge20 = allPersons.stream()
.filter(p -> p.getAge() == 20)
.collect(Collectors.toList());
System.out.println(peopleAge20);
// summary statics (average age) for all people
IntSummaryStatistics stats =
allPersons.stream().mapToInt(p -> p.getAge()).summaryStatistics();
System.out.printf("Average age: %f\n", stats.getAverage());
Note that this approach does break the idea of a Javabean, but that may or may not be an issue depending upon your requirements.
First thing, we should add a constructor to your Person class.
class Person {
public Person(String name, String title, int age) {
this.name = name;
this.title = title;
this.age = age;
}
}
Now while you read the input you can use a Map as follows. Here after reading each line, we create a Person object and then using that person's age we make an entry in the map with key as age and value as Person.
Map<Integer, Person> mapOfPeople = new HashMap<>();
while (input.hasNextLine()) {
String line[] = input.nextLine().split(",");
Perso person = new Perso(line[1], line[0], Integer.parseInt(line[2].trim()));
mapOfPeople.put(person.getAge(), person);
}
Now to fetch a particular Person by age just do
mapOfPeople.get(20);
I have Googled this for a couple of days without much luck. I am trying to read a text file and use that information to populate the private fields of an array for a class object. I am new to Java and pretty new to programming in general.
What I've come up with for reading into the array seems really clunky and I feel there must be a better way, but I cannot find a good example for this particular kind of case case.
Creating a bunch of string variables was the only way I could get this to work. Perhaps main is a bad place to do this; perhaps Scanner is a poor choice here?
What better ways are there to implement this situation?
My text file that contains Strings and integers separated by whitespace on lines is similar to this:
Joe 2541 555-1212 345 1542 Type
Bob 8543 555-4488 554 1982 Type
... etc.
Here's my majority of my code thus far which is within main:
Scanner in = new Scanner(new FileReader("accounts.txt")); //filename to import
Accounts [] account = new Accounts [10];
int i = 0;
while(in.hasNext())
{
account[i] = new Accounts();
String name = in.next();
String acct_num = in.next();
String ph_num = in.next();
String ss_num = in.next();
int open_bal = in.nextInt();
String type = in.next();
account[i].setName(name);
account[i].setAcctNum(acct_num);
account[i].setPhoneNum(ph_num);
account[i].setSSNum(ss_num);
account[i].setOpenBal(open_bal);
account[i].setType(type);
i++;
}
class Accounts
{
public Accounts()
{
}
public Accounts(String n, String a_num, String ph_num,
String s_num, int open_bal, String a_type, double close_bal)
{
name = n;
account_number = a_num;
phone_number = ph_num;
ssn = s_num;
open_balance = open_bal;
type = a_type;
close_balance = close_bal;
}
public String getName()
{
return name;
}
public void setName(String field)
{
name = field;
}
public String getAcctNum()
{
return account_number;
}
public void setAcctNum(String field)
{
account_number = field;
}
//And so forth for the rest of the mutators and accessors
//Private fields
private String name;
private String account_number;
private String phone_number;
private String ssn;
private int open_balance;
private String type;
private double close_balance;
}
I believe you need to split each line in order to get the data contained in each line. You can use the split() of the string class which will return a string[]. Then you can go through each index of the string array and pass them to the mutator methods of the account class.
Something like this maybe.
while(in.hasNext())
{
// will take each line in the file and split at the spaces.
String line = in.next();
String[] temp = line.split(" ");
account[i].setName(temp[0]);
account[i].setAcctNum(temp[1]);
account[i].setPhoneNum(temp[2] + "-" + temp[3]);
account[i].setSSNum(temp[4]);
account[i].setOpenBal((int)temp[5]);
account[i].setType(temp[6]);
// will account for blank line between accounts.
in.next();
i++;
}
The phone number gets split into two separate indices so you have to rejoin the phone number by accounting for the first 3 digits being in one index and the last 4 being in the next.
Replacing Accounts[] with Set<Accounts> would be more flexible solution as you can process either 10 lines or 10000 accounts without code changes. In general: Consider Collections vs arrays
Using Scanner seems to be reasonable in this particular case, however take a look at the others ways of processing text (performance vs convenience): Scanner vs. StringTokenizer vs. String.Split
Setting up account parameters with mutators or constructor might not be the best choice: Effective Java: Consider a builder when faced with many constructor parameters
First of all, id like to thank this fourm, as I am finding myself quickly improving through all the material on this forum and all the help different members have been giving me. So this is just a big thank you for all of that. As for my question, I've been experimenting around with input out and wanted to see if this logic would work. I am trying to get the appropriate things in their appropriate array, and wanted to see if this logic would do it. Currently (and for a while) I wont be in a place where I can access any Virtual IDE effectively so all this was kinda done on the fly using notepad, word etc. *So don't be to hard on my syntax. What I am mostly concerned about is the logic (if it would work) and to a lesser mistake any major mistakes in code.*
Thanks alot.
So basically, the text file goes like this. Title, one line of space, then name, age and wage and the separator is the #. Then right below that, name, age and wage the separator bring # etc etc.
(pretend there was no line spaces between Bobby, Sandy, Roger, Eric and David..so pretend in the txt file they are right under each other, but there is a gap in between information and bobby.
Information
Bobby#24#5.75
Sandy #19#10.22
Roger #27#6.73
Eric#31#8.99
David#12#3.50**
Here is the logic i've come up with.
public class Practice {
public static void main(String[] args) throws Exception {
String Name [] = new String [5];
int Age [] = new int [5] ;
double Wage [] = new double [5];
String Blank [] = new String [5];
FileReader inputfile = new FileReader (new File(info.txt));
BufferedReader InputBuffer = new BufferedReader (inputfile);
String Title = InputBuffer.readline (); // to get the title
int count = 0;
while (InputBuffer.readline() = null) { // this while loop grabs the blank under the title
Blank [count] = count;
}
int i = 0;
while (InputBuffer.readline() !=null) {
String Getter = InputBuffer.readline (); // reads line
String splitup= Getter.split(#); // splits it
Name [i] = splitup[i]; // puts name in this array
Age [i] = splitup([i] + 1); // age in this array
Wage [i] = splitup([i] + 2); // wage in this array
}
InputBuffer.close();
}
}
Would this logic work for storing the title in the title String, the Blank line under the Blank Array, the name under the name array, age under the age array and the wage under the wage array??
Thanks alot.
P.S: Mostly concerned about the last while loop, I want to know if it will put the name in the name array, the age in the age array and the wage in the wage array.
First of all, you only need one while-loop. I don't understand why you have two, especially since the conditional in the first is nonsensical ( InputBuffer.readline() = null ).
Your loop would look something like this:
boolean isTitleParsed = false;
String title;
String line;
while ( (line = inputBuffer.readLine()) != null ) {
if (!isTitleParsed) {
// this is the title
title = line;
isTitleParsed = true;
} else if (line.isEmpty()) {
// this is a blank line; logic for dealing with blank lines here
...
} else {
// this is actual person data
String[] personData = line.split("#");
if (personData != null && personData.length == 3) {
String name = personData[0];
String age = personData[1];
String wage = personData[2];
...
}
...
}
}
Secondly, I think using arrays is entirely the wrong way to go. Like #AVD mentioned in his comment on the OP, List<T> and a POJO is probably a much better solution -- and much more extensible.
And finally: no, as you've written it, your second loop will not successfully save the name, age, and wage to the arrays. You never increment i and the syntax splitup([i] + 1) is just wrong. (You probably meant splitup[i+1].)
Using Arrays
If you're really stuck on using arrays to save your data, you'd have to do in something like this:
String[] names = new String[5];
String[] ages = new String[5];
String[] wages = new String[5];
...
int index = 0;
while ( (line = inputBuffer.readLine()) != null && index < 5) {
if (!isTitleParsed) {
...
} else if (line.isEmpty()) {
...
} else {
// this is actual person data
String[] personData = line.split("#");
if (personData != null && personData.length == 3) {
String name = personData[0];
String age = personData[1];
String wage = personData[2];
names[index] = name;
ages[index] = age;
wages[index] = wage;
index++;
} else {
System.err.println("Line " + line + " is malformed and was not saved.");
}
...
}
}
Notice that index is instantiated at 0, but is incremented every time we save something to the arrays. This way names[0] will hold the first name, names[1] will hold the second, and so on.
Notice also that we save a given record's name, age, and wage all at the same index. So we could expect names[0] to hold "Bobby", ages[0] to hold "24", and wages[0] to hold "5.75" -- all of which are related to the same record.
Finally, the condition in the while loop has been amended to be (line = inputBuffer.readLine()) != null && index < 5. This means we'll keep looping through the lines of the file until we either run out of lines (the file ends) or our index becomes greater than 5, which is the size at which we instantiated the array. This is one reason why arrays are such a bad structure to hold this data: you have to know exactly how many records you have in your file, and you may end up not filling them all the way (you allocated too much space) or not saving some records because you have no more room to store them.
Using POJOs
A much better way to save the data would be to use a POJO -- a Plain Old Java Object. This kind of object is pretty much a "data holder" object.
In your case, it would be something like this:
public class PersonData {
private String name;
private String wage;
private String age;
public PersonData() {
this(null, null, null);
}
public PersonData(String name, String wage, String age) {
this.name = name;
this.wage = wage;
this.age = age;
}
// ... getters and setters here
}
In your code, you'd replace your arrays with a List structure of PersonData objects:
List<PersonData> records = new ArrayList<PersonData>();
And in your while loop, you'd save into these objects instead of into the arrays:
// in the else in the while loop:
String[] data = line.split("#");
if (data != null && data.length == 3) {
PersonData record = new PersonData(data[0], data[1], data[2]);
records.add(record);
} else {
// error handling for malformed line
}
Now if you wanted to get data for a particular record, you'd just need to extract the PersonData object from your records list and query it:
// assuming the first record we scraped was "Bobby#24#5.75"
PersonData person = records.get(0);
person.getName(); // returns "Bobby"
person.getAge(); // returns 24
person.getWage(); // returns 5.75
Since we're using a List and not an array, we don't have to worry about knowing exactly how many records there are in the file, and we don't run the risk of losing information because we don't have anywhere to store it.
This way we can also know for certain that a name, age, and wage are all related to the same record, whereas before we were just hoping that, say, all records at index 0 in the arrays were related to the same person.
Also, if you add additional data to the records -- for example, name#age#wage#favorite food -- all you have to do is add a new field to the PersonData object and add a line in your parsing method to add that data to the object. If you were using arrays, you'd need to add a new array, and so on.
It's also much easier to create logic if, say, you have a row that only has a name or that missing a wage, and so on -- so that you're actually able to save the data in some meaningful fashion.
If you want to make good progress in Java or any OOP Language for that matter you should always approach a problem in a Object Oriented Manner.
For the problem at hand you should always consider a class to store the Person Info rather than using associative arrays.
class PersonInfo {
PersonInfo(String name,int age,float wage) {
this.name = name;
this.age = age;
this.wage = wage;
}
String name;
int age;
float wage;
}
The code is more or less the same from above...but it should give a List of PeopleInfo as output.
List<PersonInfo> peopleInfo = new ArrayList<String>();
boolean isTitleParsed = false;
while ( (line = inputBuffer.readLine()) != null ) {
if (!isTitleParsed) {
// this is the title
title = line;
isTitleParsed = true;
continue;
} else if (line.isEmpty()) {
// this is a blank line; logic for dealing with blank lines here
} else {
String[] personData = line.split("#");
if (personData != null && personData.length == 3) {
peopleInfo.add(new PersonInfo(personData[0],personData[1],personData[2]));
}
}
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
We had a programming exam last week and I wasn't able to do it.
We were asked to make a program that will ask the user to select either of these three options:
given name
middle name
last name.
After selecting, you are asked to enter a name using scanner.
Then it will ask you if you want to try again, if you input yes, the program will loop again and if you enter the same name, it will prompt an error saying you already set it that way.
I've done all of it except that part, comparing the values.
How do I compare the 1st and 2nd input using scanner?
Here is what I have done so far.
public class PXM {
private String givenname;
private String middlename;
private String lastname;
public void setGN(String gn) {
this.givenname = gn;
}
public void setMN(String mn) {
this.middlename = mn;
}
public void setLN(String ln) {
this.lastname = ln;
}
public boolean equals() {
}
}
import java.util.*;
public class TestPXM {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String yes;
int t;
PXM p1 = new PXM(); {
System.out.println("1. given name ");
System.out.println("2. middle name");
System.out.println("3. last name");
System.out.print("select method: ");
int method = sc.nextInt();
if (method == 1) {
System.out.println("enter given name: ");
String gn = sc.next();
p1.setGN(gn);
}
}
}
}
You don't use the scanner to compare. You would save the values input and compare against those.
I would use a Set to hold the values, because Set values are guaranteed to be unique, and that suits the application. You would use Set.contains() to find if you've already got a name.
Assuming you have two Strings, s1 and s2 and you want to compare them, you should use the equals() method:
if (s1.equals(s2)) {
// strings are the same
} else {
// strings are different
}
If you don't know how to use Scanner, take a look here.
You can use this:
Since you've already set the variable in:
p1.setGN(gn);
you can read the input again after suitable prompt like:
String gn=sc.next();
and then compare the stored variable in the object p1 using a getter method:
public String getGN()
{
return this.givenname;
}
Now if you do
if(gn.equals(p1.getGN())
{
System.out. println("You have already set that");
}
You will get the desired result.