I am trying to go through a list of names with amounts.
One array has the name of the person , the other has the amount the person gave i.e. john, 55 sally 40 john 33 sarah 55.
My objective is to total the like names and print out the name of the person and the total amount that was given.
John gave twice so he should total 88. But I am getting the total right but my program is printing the name twice. So john 88 is printing twice... I know its likely because I put it in the first for loop its iterating the entire length of the array.
But I am unsure how to solve this?
import java.util.*;
public class chapterfive {
public static void main (String[]args) {
Scanner in = new Scanner (System.in);
String[]names = new String[4];
int[] scores = new int[4];
for (int i = 0; i<names.length; i++) {
names[i] = in.next();
scores[i] = in.nextInt();
}
int amount = 0;
String firstname = "";
for (int i = 0; i < names.length; i++) {
for (int j=0; j < names.length; j++) {
if (names[j].equals(names[i]))
amount += scores[j];
}
System.out.println(names[i] + " " + amount);
amount = 0;
}
}
}
You can see that they have a relationship like Name -> Score , so if you think more abstract this is a dictionary with Key (Name) and Value (Score) , so you can use another data-structure like a Map or you can use an array and make a class Person , have the arrayOrderer and when you add a new person check if that person exist in the array..
Example :
Map <String , Integer> people = new HashMap<>();
for (int i=0; i<lengthYouWant; i++)
{
String name=in.next();
int score=in.nextInt();
if(people.contains(name)){
score= people.get(name)+score;
}
people.put(name,score);
}
Should be using a Map to simplify things, rather than keeping track of two arrays. But heres a fix that may work (haven't tested it)
String firstname = "";
for (int i = 0; i < names.length; i++) {
int amount = 0;
boolean skip = false;
for (int j=0; j < names.length; j++) {
//need to skip because we have already processed it
if(names[j].equals(names[i]) && i > j) {
skip = true;
break;
}
else if (names[j].equals(names[i])) {
amount += scores[j];
}
}
if(!skip) {
System.out.println(names[i] + " " + amount);
}
}
If you make an array or list of the Person class you can implement Comparable and add a method to help in sorting.
Java is an object-oriented language, which means, among other things, that you can make your own data structures. Using parallel arrays is error prone, and it separates data you want to keep together. So, what do you need to organize this?
First is a way of storing a name and an amount. Call it Donation.
class Donation {
private final String name;
private final int amount;
public Donation(String name, String amount) {
this.name = name;
this.amount = amount;
// EXERCISE: Add error checking.
}
public String getName() { return name; }
public int getAmount() { return amount; }
public String toString() {
return "Name: " + name +", amount: " + amount;
}
}
Notice that this class's variables are final; they can't be changed once set. They are set in the constructor, and there are get methods and a toString method that replaces what you have in your System.out.println statement.
Next, you need a way of storing the data. Don't use arrays. Lists are more flexible.
private static List<Donation> donations = new ArrayList<Donation>();
// and in main:
while (true) {
String name = null;
int amount = 0;
if (in.hasNext()) {
name = in.next();
} else {
break;
}
if (in.hasNextInt()) {
amount = in.nextInt();
} else {
break;
}
donations.add(new Donation(name, amount));
} See -- no 4s.
Next, you need to consolidate the repeated donations. I mean, some people give to their church every Sunday. We'll use the appropriate structure, a Map.
// Also in main:
Map<String, Integer> totals = new HashMap<>();
for(Donation d: donations) {
String name = d.getName();
int amount = d.getAmount();
if (!totals.containsKey(name)) {
totals.put(name, 0);
}
int currentDonation = totals.get(name);
totals.put(name, currentDonation + amount);
}
And then finally, you iterate through the map and print each entry.
for ( Map.Entry<String, Integer> entry: totals.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
And now, another exercise and strategy: stop doing everything in main. Give your ChapterFive class instance variables and methods. Then, write tests for these. Try to find improvements to what I suggested. Then, see if there are libraries that can help you.
Related
There is a list of 200 students names and exam results.
My task is: "Create a constructor method for this list and put them in descending order with for statement".
I've done the first part. I can print out the list also. But I have no idea how to put them in descending order using for statement. Can anyone show me how to do that?
Current code:
package training;
public class ExamResult {
String studentName;
String examName;
int points;
String date;
ExamResult(String studentName, String examName, String date,int points) {
this.studentName=studentName;
this.examName=examName;
this.points=points;
this.date=date;
}
public void display() {
System.out.println(studentName + " " + examName + " " + date + " " + points);
}
}
package training;
public class DisplayExamResults {
public static void main (String args[]) {
ExamResult one=new ExamResult("Ryan Pena","Sociology","21/06/2016",16);
ExamResult two=new ExamResult("Portia Hamilton","Sociology","21/06/2016",34);
ExamResult three=new ExamResult("Ryan Pena","Sociology","21/06/2016",35);
one.display();
two.display();
three.display();
}
}
So, Daniel! This is going to be long because you are new to Java and I will try to explain everything. You can always read more about a lot of things here but I will explain just enough for this problem.
When you want to sort objects of a class, in your case, class ExamResult, you cannot just use a for loop on one of the fields and finish sorting. In order to achieve your desired sorting, you will need to use an interface called Comparable. This interface lets you write your own sorting criteria based on the structure of your class.
We will proceed step by step.
Step 1: Implement the Comparable interface in the ExamResult class
Since you want to sort objects of the ExamResult class, this is where you will implement the interface. By that, we mean, you will write how you want to sort your objects. We want to sort based on the student names. And for sorting, we will need to compare objects to see which one is greater than the other.
Here, we will use a term called overriding which basically means that we will override the comparison function which was declared in the Comparable interface.
Our definition below takes as input an object of the class ExamResult and compares its student name with that of the current object - this. On comparison, it returns an integer:
0, if the names are equal
>0, if the other object's student name is greater than the current one
<0, if the other object's student name is lesser than the current one
package training;
public class ExamResult implements Comparable<ExamResult> {
/* your previous code remains here as is*/
// this function returns the name of the student
public String getStudentName() { return studentName; }
#Override
// write your sorting criteria
public int compareTo(ExamResult other) {
String name1 = this.getStudentName();
String name2 = other.getStudentName();
return name1.compareTo(name2);
}
}
Step 2: Construct a list of ExamResult objects in DisplayExamResults class
Now that we have finished defining how to compare objects, we need a list of those objects on which we will run the for loop and perform the comparison.
We can do that in the DisplayExamResults class like so:
// Create a list of results on which you will run your for loop
List<ExamResult> resultList = new ArrayList<>();
resultList.add(one);
resultList.add(two);
resultList.add(three);
Here, the List interface lets you define a list of objects of any user defined class like yours. So you create a list and add the ExamResult objects to it.
Step 3: Sort using the for loop
This is the final step, where you perform the actual sorting in the DisplayExamResults class. We will first sort in ascending order and then reverse the list.
You start with a left (i) and a right (j) pointer. i is set to 0 because it starts at the beginning of the list and j is set at the end of the list.
As you keep comparing, if the object on the left is smaller than the one on the right, you just move on, i.e. increment i. Similarly, if the object on the right is greater than that on the left, just move on by decrementing j.
But, if the order is not like that, then you swap them. Which is what we do in the if statement. You can see that we are using the compareTo() function that we had defined above.
// Loop over that list to sort the objects
for (int i = 0; i < resultList.size(); i++) {
for (int j = resultList.size() - 1; j > i; j--) {
if (resultList.get(i).compareTo(resultList.get(j)) > 0) {
ExamResult temp = resultList.get(i);
resultList.set(i, resultList.get(j));
resultList.set(j, temp);
}
}
}
// For descending order
Collections.reverse(resultList);
// Display the results after sorting is over
for (ExamResult r : resultList) {
r.display();
}
Phew! Now, we put all that code together to get the following two files.
package training;
public class ExamResult implements Comparable<ExamResult> {
String studentName;
String examName;
int points;
String date;
ExamResult(String studentName, String examName, String date,int points) {
this.studentName=studentName;
this.examName=examName;
this.points=points;
this.date=date;
}
public void display() {
System.out.println(studentName + " " + examName + " " + date + " " + points);
}
// this function returns the name of the student
public String getStudentName() { return studentName; }
#Override
// write your sorting criteria
public int compareTo(ExamResult other) {
String name1 = this.getStudentName();
String name2 = other.getStudentName();
return name1.compareTo(name2);
}
}
And
package training;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DisplayExamResults {
public static void main (String args[]) {
ExamResult one = new ExamResult("Ryan Pena","Sociology","21/06/2016",16);
ExamResult two = new ExamResult("Portia Hamilton","Sociology","21/06/2016",34);
ExamResult three = new ExamResult("Ryan Pena","Sociology","21/06/2016",35);
one.display();
two.display();
three.display();
System.out.println("\n");
// Create a list of results on which you will run your for loop
List<ExamResult> resultList = new ArrayList<>();
resultList.add(one);
resultList.add(two);
resultList.add(three);
// Loop over that list to sort the objects
for (int i = 0; i < resultList.size(); i++) {
for (int j = resultList.size() - 1; j > i; j--) {
if (resultList.get(i).compareTo(resultList.get(j)) > 0) {
ExamResult temp = resultList.get(i);
resultList.set(i, resultList.get(j));
resultList.set(j, temp);
}
}
}
// For descending order
Collections.reverse(resultList);
// Display the results after sorting is over
for (ExamResult r : resultList) {
r.display();
}
}
}
I tried to explain the bits in there. Please read more and understand better. Hope it helps.
If the names are as a String Array or a List:
Using standard Java libraries:
String[] students = {"Aaron", "Jonas", "Bob", "Karl"};
Arrays.sort(students);
List<String> temp = new ArrayList<>(Arrays.asList(students));
Collections.reverse(temp);
temp.toArray(students);
OR
Using Bubblesort and chars to compare the strings:
String[] students = {"Aaron", "Jonas", "Bob", "Karl"};
char[] temp1;
char[] temp2;
int length;
for(int i = 0; i < students.length; i++){
temp1 = students[i].toLowerCase().toCharArray();
for(int n = i+1; n < students.length; n++){
temp2 = students[n].toLowerCase().toCharArray();
if(temp1.length > temp2.length)
length = temp2.length;
else
length = temp1.length;
for(int c = 0; c < length; c++){
if(temp1[c] < temp2[c]){
String temp = students[i];
students[i] = students[n];
students[n] = temp;
temp1 = students[i].toLowerCase().toCharArray();
break;
}
else if(temp1[c] > temp2[c])
break;
}
}
}
How could I remove an object inside a Linkedlist. I have a class account with studentId and studentName. I enter the objects inside the list, but when I try to remove I do not know how to do it. Because every time you remove an element from the middle of the list it gets organized, meaning the indexes change. So how can I get the studentId attribute and remove the object inside the linkedList.
Sample:
LinkedList: Account{studentId = 1, studentName = nome1} = index = 0 ,
LinkedList: Account{studentId = 2, studentName = nome2} = index = 1 ,
LinkedList: Account{studentId = 3, studentName = nome3} = index = 2.
what I would like was for the user to insert the studentId that he wants to delete and I can do a code that searches and deletes that object.
public Account{
private int studentID;
private String StudentName;
}
public static void main(String[] args){
int accountNumber;
LinkedList<Account> linkedAccount = new LinkedList<>();
Account obj1;
System.out.println("Type the acc number: ");
accountNumber = in.nextInt();
obj1 = linkedAccount.remove(accountNumber);
System.out.println("The " + obj1 + " has been deleted");
}
Every time I delete an object from the middle it changes the index of the linkedList. Rearranging. So i do not know how to do it can you help me?
If you don't need to keep a reference to the object you remove, you can just
linkedAccount.removeIf(acc -> acc.getStudentID() == accountNumber);
If you want to keep a reference to the element you remove you can
for (Account acc : linkedAccount) {
if (acc.getStudentID() == accountNumber) {
obj1 = acc;
linkedAccount.remove(acc);
break;
}
}
// OR
for (int i = 0; i < linkedAccount.size(); i++) {
if (linkedAccount.get(i).getStudentID() == accountNumber) {
obj1 = linkedAccount.remove(i);
break;
}
}
Notice that in most case and basiclly an ArrayList is sufficient When to use LinkedList over ArrayList in Java?
Currently, you're using accountNumber as the index which is incorrect, instead loop over the list and find the index of the object and then remove:
for (int i = 0; i < linkedAccount.size(); i++) {
if (linkedAccount.get(i).getStudentID() == accountNumber) {
obj1 = linkedAccount.remove(i);
break;
}
}
Further, why are you using a LinkedList instead of an ArrayList? the latter is almost always favourable.
I think the best option is to search the account in the list by the studentID and then remove it.
public Account{
private int studentID;
private String StudentName;
public int getStudentID() {
return this.studentID;
}
}
public static void main(String[] args){
int accountNumber;
LinkedList<Account> linkedAccount = new LinkedList<>();
Account obj1;
System.out.println("Type the acc number: ");
accountNumber = in.nextInt();
for (int i = 0; i < linkedAccount.size(); i++) {
if (accountNumber == linkedAccount.get(i).getStudentID()) {
System.out.println("The student " + linkedAccount.get(i).getStudentID() + " has been deleted");
linkedAccount.remove(i);
break; // This is to exit for loop, but if you want to delete every instance in the list with this ID you can skip this break
}
}
}
I am attempting to sort the values in my program using the Bubble Sort method. I believe that my code in the organisedRoom method is correct. However when I run the code, add some customers and then attempt to sort them, the program crashes. If anyone can please point me in the right direction I would greatly appreciate it.
package test;
import java.io.IOException;
import java.util.Scanner;
public class Test {
private class Customer implements Comparable<Customer>{
private String name;
public Customer(String name) {
this.name = name;
}
//Override to stop the program returning memory address as string
#Override
public String toString() {
return name;
}
#Override
public int compareTo(Customer c) {
return name.compareTo(c.name);
}
}
//Array to store customers
public Customer[] customers;
public Scanner input = new Scanner(System.in);
public Test(int nRooms) throws IOException {
customers = new Test.Customer[nRooms];
System.out.println("Welcome to the Summer Tropic Hotel\n");
chooseOption();
}
final JFileChooser fc = new JFileChooser();
// Call new Hotel with int value to allocate array spaces
public static void main(String[] args) throws IOException {
Test t = new Test(11);
}
// New procedure to return User input and point to next correct method
private String chooseOption() throws IOException {
// Set to null, this will take user input
String choice;
//Menu options
System.out.println("This is the Hotel Menu. Please choose from the following options:\n");
System.out.println("A: " + "This will add a new entry\n");
System.out.println("O: " + "View booked rooms, in order of customers name.\n");
System.out.println("X: " + "Exit the program\n");
// Take user input and assign it to choice
choice = input.next();
// Switch case used to return appropriate method
switch (choice.toUpperCase()) {
case "A" :
System.out.println("");
addCustomer();
return this.chooseOption();
case "O" :
System.out.println("");
organisedRoom();
return this.chooseOption();
case "X":
System.exit(0);
}
return choice;
}
// Add a new customer to the Array
public void addCustomer() throws IOException {
// New variable roomNum
int roomNum = 1;
// Loop
do {
// Take user input as room number matching to array index - 1
System.out.println("Please choose a room from 1 to 10");
roomNum = input.nextInt() - 1;
// If room is already booked print this
if (customers[roomNum] != null) {
System.out.println("Room " + roomNum + 1 + " is not free, choose a different one.\n");
this.addCustomer();
}
// Do until array index does not equal to null
} while (customers[roomNum]!= null);
System.out.println("");
// User input added to array as name replacing null (non case-sensetive)
System.out.println("Now enter a name");
customers[roomNum] = new Customer(input.next().toLowerCase());
// Customer (name) added to room (number)
System.out.println(String.format("Customer %s added to room %d\n", customers[roomNum], roomNum + 1));
}
private void organisedRoom() {
boolean flag = true;
Customer temp;
int j;
while (flag) {
flag = false;
for (j = 0; j < customers.length - 1; j++) {
if (customers[j].compareTo(customers[j+1]) < 0) {
temp = customers[j];
customers[j] = customers[j + 1];
customers[j + 1] = temp;
flag = true;
}
}
}
}
}
I think this is because the initialisation of the array adds null to all the array index places.
The stack trace is as follows:
Exception in thread "main" java.lang.NullPointerException
at test.Test$Customer.compareTo(Test.java:34)
at test.Test.organisedRoom(Test.java:133)
at test.Test.chooseOption(Test.java:83)
at test.Test.chooseOption(Test.java:79)
at test.Test.chooseOption(Test.java:79)
at test.Test.<init>(Test.java:46)
at test.Test.main(Test.java:55)
Java Result: 1
It fails because you create Customer[] which will be initialized with11 null references. If you want to order them all elements in the array will be compared. Which lead into the java.lang.NullPointerException.
Store the Customer in an ArrayList. Then you should be able to prevent this error.
edit
If you really need to stick as close as possible to your current code. The following would fix your sorting. (don't use this solution for a real life project)
private void organisedRoom() {
for (int i = customers.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (customers[j + 1] == null) {
continue;
}
if (customers[j] == null ||customers[j + 1].compareTo(customers[j]) < 0) {
Customer temp = customers[j + 1];
customers[j + 1] = customers[j];
customers[j] = temp;
}
}
}
System.out.println("show rooms: " + Arrays.toString(customers));
}
edit 2
To keep most of your current code, you might store the room in the Customer instance (which I personally would not prefer).
// change the constructor of Customer
public Customer(String name, int room) {
this.name = name;
this.room = room;
}
// change the toString() of Customer
public String toString() {
return String.format("customer: %s room: %d", name, room);
}
// store the Customer like
customers[roomNum] = new Customer(input.next().toLowerCase(), roomNum);
Your implementation of Bubble Sort is incorrect. It uses nested for loops.
for(int i = 0; i < customers.length; i++)
{
for(int j = 1; j < (customers.length - i); j++)
{
if (customers[j-1] > customers[j])
{
temp = customers[j-1];
customers[j-1] = customers[j];
customers[j] = temp;
}
}
}
I managed to write the code below which works, however when printing, it only prints the ratings in order but not the sentences. How do I sort the sentences along the rating given in order??
public static void loopswithinloops()
{
String[] sentences = {"I am blessed to have you in my life. You are the one thing in my life that is true and real",
"I am honoured to have you by my side to love and to cherish each day of our lives.",
"More precious than any other thing in my life is to see your face each and every day",
"To wake up beside you is a treasure that I have found in you and that I am thankful for.",
"Your beautiful eyes dance bright and clear and I can see forever in your eyes." };
for (int i=0; i<=1; i++)
{
ratemessage(sentences); //this will loop the whole rating message two times from 0 to 1.
}
}
public static void ratemessage (String[] sentences) // this will receive the argument from the method defined above and then be printed below as shown.
{
int[] result = new int[sentences.length];//you have to give the array a size
String inputStr;
for (int i = 0; i < sentences.length; i++)
{
JOptionPane.showMessageDialog(null, sentences[i]);//the sentences one at at time
inputStr = JOptionPane.showInputDialog("what do you rate this sentence out of 10?");
result[i] = (int)Float.parseFloat(inputStr);//put the input into the array - it comes as a float so you'll have to cast it to int
}
sort (result, sentences);
printsort (result, sentences);
}
public static void sort( int [] result , String [] sentences)
{
int temp;
for(int i = 0; i < result.length; i++)
{
for(int j = 1; j < (result.length -i); j++)
{
//if numbers[j-1] > numbers[j], swap the elements
if(result[j-1] > result[j])
{
temp = result[j-1];
result[j-1]=result[j];
result[j]=temp;
}
}
}
}
public static void printsort (int [] result , String [] sentences)
{
System.out.println("The ratings go in ascending order: ");
for(int i = 0; i < result.length; i++)
{
System.out.println("Your ascending rating is " + result[i]+ " " + sentences[i]);
}
}
Rather than just supplying the code to fix this specific issue, I will give a pointer on how to restructure it to make it much more intuitive. I'm using Java 8 features but it's easy to convert back if required.
Create a class that holds both the message and the rating.
public class RatedMessage {
private final String message;
private final int rating;
public RatedMessage(String message, int rating) {
this.message = message;
this.rating = rating;
}
public String toString() {
return rating + ": " + message;
}
public static int compareRating(RatedMessage rm1, RatedMessage rm2) {
return rm1.rating - rm2.rating;
}
}
Then create a list of RatedMessage objects
List<RatedMessage> ratedMessages = new ArrayList<>();
Alter your message rating method to create a RatedMessage for each rated message and add it to the list.
ratedMessages.add(new RatedMessage(message, rating));
Then sort your list using the rating:
Collections.sort(ratedMessages, RatedMessage::compareRatings);
Then print out the sorted list:
ratedMessages.stream().map(RatedMessage::toString).forEach(System.out::println);
So I have to find the minimum in an array in Java, but with that I have to print out the corresponding names that go with the minimum in another parallel array. Inside my for loop where I find the minimum, I have a variable place that I set equal to my counter variable from the for loop when the minimum is changed. But every time I print out the name, it prints out the first name in the array instead of the name in the place holder.
public double getMinimum(double[] money)
{
double lowest = money[0];
for (int p = 0; p < money.length; p++)
{
if (money[p] < lowest)
{
lowest = money[p];
place = p;
}
}
return lowest;
}
Theres the for loop within my programmer-defined class that finds the minimum.
public String getFirstNameMin(String[] firstName)
{
String minFirstName;
minFirstName = firstName[place];
return minFirstName;
}
This is the code I'm using to figure out the first name from the first names array at that place. What am I doing wrong? I'm kinda new to Java, but I did all this array stuff in C++ before, so idk if I am missing something very simple, or its different in Java.
I would say try making a separate class for this that contains the user and the money:
public class User {
private double money;
private String fname;
private String lname;
//getters/setters/constructors
}
Then from there you can simply compare the accounts:
public User getMinimum(User[] users) {
if (users.length <= 0) {
return null;
}
User lowest = users[0];
for (int i = 1; i < users.length; i++) {
if (users[i].getMoney() < lowest.getMoney()) {
lowest = users[i];
}
}
return lowest;
}
Try this:
public int getMinIndex(double[] money)
{
double min = money[0];
int minIndex = 0;
for (int p = 0; p < money.length; p++)
{
if (money[p] < min)
{
min = money[p];
minIndex = p;
}
}
return minIndex;
}
public static void main(String[] args)
{
double[] money;
String[] name;
//... init your arrays here!
int index = getMinIndex(money);
System.out.println("Min money = " + money[index] + "; name = " + name[index]);
}
However, following an object oriented approach rogues solution is much nicer!!!