How can I label the duplicated elements? - java

I got a name list that needs to convert to the result that person with same last name are all labeled. For example:
origin list:
JayReese
ClaraSmith
JohnSmith
output:
JayReese
ClaraSmith1
JohnSmith2
The code of Person class are written below, how can I compare all the lastName and when there are duplicated lastName, unique index is added to each? What method should be added?
I'd really appreciate any input and or help. Thank you very much.
import java.util.*;
public class Person implements Comparable<Person> {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String toString() {
return lastName + firstName;
}
}

First, either edit the Person class or create a new class that has an index field that can be set. Comparability is completely unnecessary for your usecase.
public class Person {
private String firstName;
private String lastName;
public int index;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String toString() {
return lastName + firstName + (index != 0 ? index : "");
}
}
You can use a HashMap<String, Integer> to add the numbering to the last name, like this:
public static void numberDuplicateLastNames(List<Person> people) {
HashMap<String, Integer> duplicatedLastNames = new HashMap<>();
for(Person p : people) {
if(! duplicatedLastNames.containsKey(p.lastName)) {
duplicatedLastNames.put(p.lastName, 1);
p.index = 1;
} else {
int i = duplicatedLastNames.get(p.lastName) + 1;
duplicatedLastNames.put(p.lastName, i);
p.index = i;
}
}
//Remove index from the people who don't have a duplicate last name
for(Person p : people) {
if (duplicatedLastNames.get(p.lastName) == 1) {
p.index = 0;
}
}
}

You could do a compare method like this
public compairLastName(String LastName){
if(lastName.equals(LastName){
System.out.println("These last names are the same");
}else{
System.out.println("These last names are not the same");
}

So you asked about labelling (and by extension sorting), but refer to uniquely identifying - here is an answer to both :)
For Sorting
Real life programs deal with that every day, just ensure your comparable code by default sorts by 2 attributes
LastName
FirstName
If they compare in that order, you should end up with:
XavierAllen
JayReese
BillySmith
ClaraSmith
JohnSmith
To compare multiple attributes, I would refer you to this stackoverflow topic, which shows how to do both single and multiple comparisons on a Person object with the same field names even ; )
How to compare objects by multiple fields
For Unique Referance
Also, if you were concerned about uniquely identifying the Person outside of simple comparison sorting, then you would add an int field (or guid, or whatever your flavour) that would hold a unique value
Basically same as a Database PK - you would never use a persons name as a PK in a database, so your Person ideally should have a property like that too.
If you wanted to add this PK to your toString() then go for it
import java.util.*;
public class Person implements Comparable<Person> {
private int personID;
private String firstName;
private String lastName;
public Person(String firstName, String lastName, int personID) {
this.firstName = firstName;
this.lastName = lastName;
this.personID = personID;
}
public int getID(){
return this.personID;
}
public String toString() {
return this.personID + ": " + this.lastName + ", " + this.firstName;
}
}
#Mshnik did post a method for dynamically adding PK, but youd be much better off checking the Person collection or some high level variable to find the last personID and go from there - else that dynamic value can only be used in the most limited of contexts, and you may as well just use the index its located at in the Person collection you are retrieving it from

Here's brute force way of labeling your Person objects that doesn't rely on using Maps to count last name occurrences.
I've also include another method to exploit the power of Java 8 streams. IMO, the brute force method is more understandable, but I have not done any benchmark testing to know which is more efficient. So I'll leave that up to commenting.
public static void main(String[] args) throws Exception {
List<Person> persons = new ArrayList() {
{
add(new Person("Jay", "Reese"));
add(new Person("Clara", "Smith"));
add(new Person("John", "Smith"));
add(new Person("James", "Smith"));
add(new Person("Christie", "Mayberry"));
add(new Person("Matthew", "Mayberry"));
}
};
// Toggle calls to see results
bruteForceLabel(persons);
// java8StreamLabel(persons);
}
public static void bruteForceLabel(List<Person> persons) {
for (int i = 0; i < persons.size(); i++) {
Person currentPerson = persons.get(i);
char lastCharacter = currentPerson.lastName.charAt(currentPerson.lastName.length() - 1);
// Only process last names that are not labeled
if (lastCharacter < '0' || '9' < lastCharacter) { // Not a digit
int counter = 2;
boolean foundDuplicateLastName = false;
for (int j = i + 1; j < persons.size(); j++) {
Person nextPerson = persons.get(j);
if (nextPerson.lastName.equals(currentPerson.lastName)) {
foundDuplicateLastName = true;
// Label the next person with the counter then
nextPerson.lastName = nextPerson.lastName + counter;
counter++;
}
}
// Label the current person with the starting sequence
if (foundDuplicateLastName) {
currentPerson.lastName = currentPerson.lastName + 1;
}
}
}
System.out.println(persons);
}
public static void java8StreamLabel(List<Person> persons) {
// Get a distinct count of all last names
Map<String, Long> lastNames = persons
.stream()
.map(p -> p.lastName)
.distinct()
.collect(Collectors
.toMap(p -> p, p -> persons
.stream()
.filter(p2 -> p2.lastName.equals(p)).count()));
// Apply number sequence to duplicate last names
lastNames.keySet().stream().filter((key) -> (lastNames.get(key) > 1)).forEach((key) -> {
int counter = 1;
for (Person person : persons.stream().filter(p -> p.lastName.equals(key)).toArray(size -> new Person[size])) {
person.lastName = person.lastName + counter;
counter++;
}
});
// Display the modified list
System.out.println(persons);
}
public static class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String toString() {
return firstName + " " + lastName;
}
}
Results:
[Jay Reese, Clara Smith1, John Smith2, James Smith3, Christie Mayberry1, Matthew Mayberry2]

Related

How can i use a for loop to create objects with params?

I try to create objects in a for loop like:
String[] empArr[] = {
{"Moe","Jude","Employee","2017"},
{"Noe","Joel","Employee","2019"},
{"Poe","Juce","Employee","2021"}
};
Employee[] emp;
emp = new Employee[empArr.length];
// get length and loop from empArr[], here there are 3 entries
for (int i=0; i<=empArr.length-1; i++) {
// get length and loop from empArr[i], here there are 4 entries
for (int j=0; j<=empArr[i].length-1; j++) {
// create objects in loop from empArr[i] with params from empArr[i][0 ]
emp[i] = new Employee(empArr[i][0],empArr[i][1],empArr[i][2],empArr[i][3]);
}
// create from a method the output and get here all firstNames from empArr[]
output(emp[i].getInfo("firstName"));
}
This is working and I get the output I want.
But I use in the middle part at the moment:
for (int j=0; j<=empArr[i].length-1; j++) {
emp[i] = new Employee(empArr[i][0],empArr[i][1],empArr[i][2],empArr[i][3]);
}
Is there a possibility to make a loop of j for the arguments of the object too?
Something like:
emp[i] = new Employee(
for (int j=0; j<=empArr[i].length-1; j++) {
empArr[i][j];
}
);
I tried this code above, but i cant get it working:
I cant imagine a solution, hope for help
best regards
Unless I miss-read this post (which could be likely), you can do it this way. Read the comments in code:
The Employee Class (you didn't post yours):
public class Employee {
private String firstName;
private String lastName;
private String employeeStatus;
private String yearOfHire;
// An Employee class Constructor specific to the desired need:
public Employee(String firstName, String lastName,
String employeeStatus, String yearOfHire) {
this.firstName = firstName;
this.lastName = lastName;
this.employeeStatus = employeeStatus;
this.yearOfHire = yearOfHire;
}
//GETTERS & SETTERS
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmployeeStatus() {
return employeeStatus;
}
public void setEmployeeStatus(String employeeStatus) {
this.employeeStatus = employeeStatus;
}
public String getYearOfHire() {
return yearOfHire;
}
public void setYearOfHire(String yearOfHire) {
this.yearOfHire = yearOfHire;
}
#Override
public String toString() {
return firstName + ", " + lastName + ", " + employeeStatus + ", " + yearOfHire;
}
}
The code to use the above Employee class:
String[][] empArr = {
{"Moe","Jude","Employee","2017"},
{"Noe","Joel","Employee","2019"},
{"Poe","Juce","Employee","2021"}
};
// Declare a List to hold instances of Employee:
List<Employee> employeeInstances = new ArrayList<>();
/* Variables to be filled from 2D Array and passed
to Employee constructor: */
String fName, lName, emplStatus, hireYear;
// Iterate 2D Array Rows:
for (String[] ary : empArr) {
// Default string variables with "N/A" (Not Available):
fName = "N/A"; lName = "N/A";
emplStatus = "N/A"; hireYear = "N/A";
/* Iterate through the current inner Array (row) and fill
above variables to use in Employee constructor: */
for (int i = 0; i < ary.length; i++) {
/* Use 'Ternary Operator' to handle Array elements
that are Null String (""): */
fName = !ary[0].isEmpty() ? ary[0] : fName;
lName = !ary[1].isEmpty() ? ary[1] : lName;
emplStatus = !ary[2].isEmpty() ? ary[2] : emplStatus;
hireYear = !ary[3].isEmpty() ? ary[3] : hireYear;
}
// Create and Add an instance of Employee to the employeeInstances List:
employeeInstances.add(new Employee(fName, lName, emplStatus, hireYear));
}
/* Do whatever you want with the instances of Employee contained
within the employeeInstances List, for example: */
System.out.println("List all employees to Console Window:");
// Iterate through the employeeInstances List:
for (Employee empl : employeeInstances) {
// Display data for current Employee instance:
System.out.println(empl.toString());
}
System.out.println();
System.out.println("List all employees first and last names "
+ "to Console Window:");
// Iterate through the employeeInstances List:
for (Employee empl : employeeInstances) {
/* Display the first and last name of each Employee instance
contained within the employeeInstances List. Employee class
Getter methods are used to get the First and Last names from
the current instance: */
System.out.println(empl.getFirstName() + " " + empl.getLastName());
}
Console Window should display:
List all employees to Console Window:
Moe, Jude, Employee, 2017
Noe, Joel, Employee, 2019
Poe, Juce, Employee, 2021
List all employees first and last names to Console Window:
Moe Jude
Noe Joel
Poe Juce

How to use a secondary alphabetical sort on a string list of names?

I'm trying a way that when given a string of names which are first and last names, where names are split by ; and first name split to last name by : ->
"Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"
I want to return a string which is sorted out all the names as uppercase and sorted alphabetically according to the last name and the ones that share the same last name then sort again (secondary sort) between the first names of the people that share the same last name. (I also on purpose change everything to UPPERCASE).
And return a string of the sorted names, so for the example above it should return:
"(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"
which sorts according to the last name alphabetically then sorts between those who share the same last name a secondary sort of the first names.
I managed to do the main sorting which is sorting the last names alphabetically but I'm not sure how to do the secondary sorting (between those who share the same last name). I was thinking to split into sub-arrays or something similar but I'm not sure how to do this.
What is the solution for this?
Here is what I managed so far (works on main sorting):
public class Solution {
public static String meeting(String s) {
String m = "";
List<String> name = new ArrayList<String>();
for (String i : s.toUpperCase().split(";")) {
String[] n = i.split(":");
name.add(n[0] + " " + n[1]);
}
//main sorting
java.util.Collections.sort(name);
//secondary sorting and go through each different last name
for (String i : name) {
String[] n = i.split(" ");
String lastname = n[1];
// new list for the ppl who share same last name
List<String> samel = new ArrayList<String>();
samel.add(n[0]);
for (String ss : name) {
String[] nn = ss.split(" ");
if (nn[1] == lastname) {
samel.add(nn[0]);
}
}
//sort the ppl alphabetically with the same last name
java.util.Collections.sort(samel);
}
for (String i : name) {
String[] n = i.split(" ");
m += ("(" + n[0] + " , " + n[1] + ")");
}
return m;
}
}
I attempted to do the secondary sorting and was not successful.
If I wasn't clear enough, there are two sortings, the main which is by last names alphabetically and the secondary sorting which only happens on people who share the exact same last name then their first names get sorted accordingly by alphabet. So, if we have two persons called matt cohn and mill cohn, then they share the same last name and the same first letter in the last name, but a is before o, so the output should be (COHN , MATT)(COHN, MILL) and not the other way round.
On the solution down below I ran it and got an error:
input String:
Alexis:Wahl;John:Bell;Victoria:Schwarz;Abba:Dorny;Grace:Meta;Ann:Arno;Madison:STAN;Alex:Cornwell;Lewis:Kern;Megan:Stan;Alex:Korn
Actual: (ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(STAN, MADISON)(SCHWARZ, VICTORIA)(STAN, MEGAN)(WAHL, ALEXIS)
Expect: (ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(SCHWARZ, VICTORIA)(STAN, MADISON)(STAN, MEGAN)(WAHL, ALEXIS)
false
but came out as false
If you are using Java stream you can use sorted like this:
return Arrays.stream(s.split(";"))
.map(p -> p.split(":"))
.sorted(Comparator.comparing((String[] p) -> p[1]).thenComparing((String[] p) -> p[0]))
.map(p -> String.format("(%s, %s)", p[1].toUpperCase(), p[0].toUpperCase()))
.collect(Collectors.joining());
Outputs
(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)
I would also suggest to use Objects and not one String to store your information, it is not a good practice to use this.
One possible solution could be like so:
public class ExtractAndSortNames {
public static String extractAndSort(String s) {
return Stream.of(s.split(";"))
.map(String::toUpperCase)
.map(ExtractAndSortNames::extractPersonFirstNameAndLastName)
.sorted(Comparator.comparing(FirstNameAndLastName::getLastName).thenComparing(FirstNameAndLastName::getFirstName))
.map(FirstNameAndLastName::format)
.collect(Collectors.joining());
}
private static FirstNameAndLastName extractPersonFirstNameAndLastName(String personName) {
var split = personName.split(":");
var firstName = split[0];
var lastName = split[1];
return new FirstNameAndLastName(firstName, lastName);
}
private static class FirstNameAndLastName {
private final String firstName;
private final String lastName;
public FirstNameAndLastName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String format() {
return String.format("(%s, %s)", this.lastName, this.firstName);
}
}
}
Solution without streams:
public class ExtractAndSortNames {
public static String extractAndSort(String s) {
List<FirstNameAndLastName> toSort = new ArrayList<>();
for (String s1 : s.split(";")) {
String toUpperCase = s1.toUpperCase();
FirstNameAndLastName firstNameAndLastName = extractPersonFirstNameAndLastName(toUpperCase);
toSort.add(firstNameAndLastName);
}
toSort.sort(Comparator.comparing(FirstNameAndLastName::getLastName).thenComparing(FirstNameAndLastName::getFirstName));
StringBuilder sb = new StringBuilder();
for (FirstNameAndLastName firstNameAndLastName : toSort) {
String format = firstNameAndLastName.format();
sb.append(format);
}
return sb.toString();
}
private static FirstNameAndLastName extractPersonFirstNameAndLastName(String personName) {
var split = personName.split(":");
var firstName = split[0];
var lastName = split[1];
return new FirstNameAndLastName(firstName, lastName);
}
private static class FirstNameAndLastName {
private final String firstName;
private final String lastName;
public FirstNameAndLastName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String format() {
return String.format("(%s, %s)", this.lastName, this.firstName);
}
}
}
And test:
class ExtractAndSortNamesTest {
#Test
void test() {
var input = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
var result = ExtractAndSortNames.extractAndSort(input);
assertEquals("(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)", result);
}
#Test
void test2() {
var input = "Alexis:Wahl;John:Bell;Victoria:Schwarz;Abba:Dorny;Grace:Meta;Ann:Arno;Madison:STAN;Alex:Cornwell;Lewis:Kern;Megan:Stan;Alex:Korn";
var result = ExtractAndSortNames.extractAndSort(input);
assertEquals("(ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(SCHWARZ, VICTORIA)(STAN, MADISON)(STAN, MEGAN)(WAHL, ALEXIS)", result);
}
}
Bonus round using Java 15 with preview feature:
public class ExtractAndSortNames {
public static String extractAndSort(String s) {
return Stream.of(s.split(";"))
.map(String::toUpperCase)
.map(FirstNameAndLastName::from)
.sorted(Comparator.comparing(FirstNameAndLastName::lastName).thenComparing(FirstNameAndLastName::firstName))
.map(FirstNameAndLastName::format)
.collect(Collectors.joining());
}
private static record FirstNameAndLastName (String firstName, String lastName) {
private static FirstNameAndLastName from(String personName) {
var split = personName.split(":");
var firstName = split[0];
var lastName = split[1];
return new FirstNameAndLastName(firstName, lastName);
}
public String format() {
return "(%s, %s)".formatted(this.lastName, this.firstName);
}
}
}
You can use a chain of comparators to sort first by one value and then by another value:
String str = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;" +
"Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
List<Map.Entry<String, String>> list = Stream.of(str)
.map(String::toUpperCase)
// Stream<String>
.flatMap(s -> Arrays.stream(s.split(";")))
// Stream<String[]>
.map(s -> s.split(":"))
// Stream<Map.Entry<String,String>>
.map(arr -> Map.entry(arr[1], arr[0]))
// sort by last name, then by first name
.sorted(Map.Entry.<String, String>comparingByKey()
.thenComparing(Map.Entry::getValue))
.collect(Collectors.toList());
// output line by line
list.forEach(System.out::println);
Output:
CORWILL=ALFRED
CORWILL=FRED
CORWILL=RAPHAEL
CORWILL=WILFRED
TORNBULL=BARNEY
TORNBULL=BETTY
TORNBULL=BJON
See also: How to sort by a field of class with its own comparator?

The for loop in the method gets skipped when 3rd entry goes in. JAVA

When I run this code, for some reason when it hits test10 to be added into the Array sort, the addListing method ignores the for loop and just skips to the bottom. I am curious why the for loop runs for test2.addListing(test); and test2.addListing(test9); but not for the one after.
import java.util.Scanner;
public class TestListings {
public static void main(String[] args) {
StudentListings test = new StudentListings();
StudentListings test9 = new StudentListings();
StudentListings test10 = new StudentListings();
test.input();
test9.input();
test10.input();
Scanner sc = new Scanner(System.in);
int aSize = 0;
System.out.print("Enter Array Size: ");
aSize = Integer.parseInt(sc.nextLine());
ArraySort test2 = new ArraySort(aSize);
test2.addListing(test);
test2.addListing(test9);
test2.addListing(test10);
test2.showAllListings();
}
}
This is the method written, and it runs for the first run through, next = 0; intially, but the 3rd time (in test10) it just looks at the line and skips it.
public class ArraySort
{
private StudentListings[] data;
private int size = 0;
private int next = 0;
public ArraySort()
{
data = new StudentListings[size];
size = 0;
next = 0;
}
public ArraySort(int ArraySize)
{
size = ArraySize;
data = new StudentListings[size];
next = 0;
}
public void addListing(StudentListings newListing)
{
System.out.print(next);
for(i = next - 1; i <= 0; i--)
{
try {
if (newListing.compareTo(data[i].getLName()) < 0)
{
data[i+1] = data[i].deepCopy();
}
else
{
data[i+1] = newListing;
next++;
break;
}
}
catch(ArrayIndexOutOfBoundsException | NullPointerException exception)
{
int x = i + 1;
data[x] = newListing;
next++;
break;
}
}
System.out.print(next);
}
public void showAllListings()
{
for(int i = 0; i < next; i++)
{
System.out.println((i + 1) + ". " + data[i]);
}
}
}
This is the class that is getting created to be inserted into the array.
import java.util.Scanner;
public class StudentListings {
private String firstName;
private String lastName;
private int id;
private double gpa;
public StudentListings()
{
firstName = "";
lastName = "";
id = 0;
gpa = 0.0;
}
public StudentListings(String firstName, String lastName, int id,
double gpa)
{
this.firstName = firstName;
this.lastName = lastName;
this.id = id;
this.gpa = gpa;
}
public void setName(String firstName, String lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
public String getName()
{
return firstName + " " + lastName;
}
public void setId(int id)
{
this.id = id;
}
public int getId()
{
return id;
}
public void setGpa(double gpa)
{
this.gpa = gpa;
}
public double getGpa()
{
return gpa;
}
public String getLName()
{
return lastName;
}
public void input()
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter First Name: ");
this.firstName = sc.nextLine();
System.out.print("Enter Last Name: ");
this.lastName = sc.nextLine();
System.out.print("Enter Student ID: ");
this.id = sc.nextInt();
System.out.print("Enter Student GPA: ");
this.gpa = Double.parseDouble(sc.next());
}
public String toString()
{
return "Last Name: " + lastName + " First Name: " + firstName + " ID:
" + id + " GPA: " + gpa;
}
public StudentListings deepCopy()
{
StudentListings clone = new StudentListings(firstName, lastName, id,
gpa);
return clone;
}
public int compareTo(String targetKey)
{
return(lastName.compareTo(targetKey));
}
}
If next is 0 the first time then it’s 2 the third time and i starts at 1 so the condition i <= 0 is false from the start
I'm not solving that problem, because in my opinion you're trying to do (intricately) something already defined in Java. When you create a class, and have to manage an array of object of that class, Java offers a very simple way to do that, I'll explain what I would do in your position step by step:
1 - The first thing to do is to define the comparison between the object belonging to that class, you can achieve that by overriding the method compareTo of that class (the class has to implement Comparable <YourObject>); in your case i guess it schould be something like:
public class StudentListings implements Comparable<StudentListings>{
...
#Override
public int compareTo(StudentListings element){
return ...;
}
}
In which you define when a StudentListing object is bigger than another.
2 - The second thing to do is to define an ArrayList<StudentListings> in your main, and initialize it:
ArrayList<StudentListings> yourArray = new ArrayList<>();
3 - Then you have to add the elements to that array (obviously after you initialized them):
yourArray.add(test);
yourArray.add(test9);
yourArray.add(test10);
4 - Now you have your array, not sorted, to sort it you just have to call the method
Collections.sort(yourArray);
Now you have your ArrayList of StudentListings sorted.
There is another way to achieve this result, that is described here, I don't like it very much because using that way you have to redefine the comparison everytime you need to sort an array and because your main code results more complex, but it has the same result of the steps I explained (therefore the linked method is useful if you have to sort two different arrays of the same class objects in different ways, eg. one by students name and the other by students surname).

Need help creating class to return names in reverse and return initials

For homework, I need to write a class Name that has two constructors, one with 3 arguments for first, last, and middle initial, and one with two arguments for just first and last. I have to make the methods getNormalOrder, getReverseOrder, and getInitials. So if the name was John W Smith, getReverseOrder would return Smith, John W., getInitials would return JWS, and getNormalOrder would return it regularly. I keep getting the error:
method getInitials in class Name cannot be applied to given types;
when I test the method in another file. I'll put my code below.
class Name {
private String firstName;
private String lastName;
private char middleName;
public Name(String firstName, char middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getReverseOrder(String first, char middle, String last) {
String a = "";
a += last;
a += ", ";
a += first;
a += " ";
a += middle;
return a;
}
public String getReverseOrder(String first, String last) {
String a = "";
a += last;
a += ", ";
a += first;
return a;
}
public String getInitials(String first, char middle, String last) {
String a = "";
a += first.charAt(0);
a += middle;
a += last.charAt(0);
return a;
}
public String getInitials(String first, String last) {
String a = "";
a += first.charAt(0);
a += last.charAt(0);
return a;
}
}
I haven't written getNormalOrder yet. This is how I'm testing it right now. I think I did everything completely wrong.
public class NameTest {
public static void main (String [] args) {
Name teacher = new Name("John", 'W', "Smith");
Name tf = new Name("John", "Smith");
System.out.println(teacher.getInitials());
}
}
The problem is, you call the method with no arguments
teacher.getInitials()
But the methods defined in your class take 2 and 3 arguments, respectively
getInitials(String first, String last)
getInitials(String first, char middle, String last)
You don't need any arguments for these methods as the necessary data (first, middle, last) is already stored in a class member. The method should use these. The same is true for the other methods.
As an example for getInitials() (with only first and last name)
public String getInitials() {
String a = "";
a += firstName.charAt(0);
a += lastName.charAt(0);
return a;
}
Your getInitials method shouldn't require any arguments. It should return a value using class members. You can use this.first to distinguish class members and local variables.

How to fix this logical error in reading a file to a hashmap

I am passing in
String str = "First Name: John\n Last Name: GrannySmith\nBirthday: January 1 2014\n First Name: George\n Last Name: Smith\nBirthday: January 2 2014 ";
into the following method
public static void sortMap(String str) {
String[] parsedInput = str.split("\n");
Set<String> information = new HashSet<String>();
Map<String, Set<String>> myMap = new HashMap<String, Set<String>>();
for (int i = 0; i < parsedInput.length; i++) {
String firstName = "";
if (parsedInput[i].startsWith("First Name")) {
firstName = parsedInput[i].split(": ")[1];
} else {
while (!(parsedInput[i].startsWith("First Name"))) {
information.add(parsedInput[i].split(": ")[1]);
}
}
myMap.put(firstName, information);
System.out.println(myMap.get(firstName));
}
}
What I am trying to do is store my data into a hashmap where utimatley if the user enters in their first name then i can display their entire information. The information is being stored in a file. The file is being read. I have split the file where ever there is a next line. If the next like happens to be First name I then know that I want to have a new key and value that is why I have the if statements. The while loop is to ensure that all the information of that person is stored for that particular key (such that if I add in address, id etc it will all be stored within that particular key). When I run this I get a result of "[]". As opposed to the information. I am not sure where I am going wrong with my logic here? It also seems that I am stuck in an infinite loop.
There was a lot wrong with your method, you might have better luck with something like this
// Removes whitespace (if in not null), otherwise returns "".
private static String safeTrim(String in) {
if (in != null) {
return in.trim();
}
return "";
}
public static class Info {
private String firstName;
private String lastName;
private String birthDay;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = safeTrim(firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = safeTrim(lastName);
}
public String getBirthDay() {
return birthDay;
}
public void setBirthDay(String birthDay) {
this.birthDay = safeTrim(birthDay);
}
public Info(String firstName, String lastName,
String birthDay) {
setFirstName(firstName);
setLastName(lastName);
setBirthDay(birthDay);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("First Name: ").append(firstName)
.append('\n');
sb.append("Last Name: ").append(lastName)
.append('\n');
sb.append("Birthday: ").append(birthDay);
return sb.toString();
}
}
// Create and return a Map of the Object type above.
public static Map<String, Info> sortMap(String str) {
// start parsing at first name.
String[] firstNames = str.split("First Name");
Map<String, Info> map = new HashMap<String, Info>();
for (String nameStr : firstNames) {
nameStr = safeTrim(nameStr);
if (nameStr.length() > 0) {
// add back the key name -
nameStr = "First Name" + nameStr;
String[] fields = nameStr.split("\n");
// The three fields to find...
String firstName = "";
String lastName = "";
String birthDay = "";
for (String f : fields) {
// split name-value.
String[] nv = safeTrim(f).split(":");
if (nv.length != 2) {
continue;
}
nv[0] = safeTrim(nv[0]);
if (nv[0].equalsIgnoreCase("First Name")) {
firstName = safeTrim(nv[1]);
} else if (nv[0]
.equalsIgnoreCase("Last Name")) {
lastName = safeTrim(nv[1]);
} else {
birthDay = safeTrim(nv[1]);
}
}
map.put(firstName, new Info(firstName,
lastName, birthDay));
}
}
return map;
}
public static void main(String[] args) {
String str = "First Name: John\n Last Name: GrannySmith\n"
+ "Birthday: January 1 2014\n First Name: George\n "
+ "Last Name: Smith\nBirthday: January 2 2014 ";
Map<String, Info> map = sortMap(str);
System.out.println(map.get("John"));
}
Which, when I run it, outputs
First Name: John
Last Name: GrannySmith
Birthday: January 1 2014

Categories