Problem: My overloading constructors are undefined, even though I'm doing the right thing (I think so?).
The source code:
class Book {
String section;
float subject2;
char section2, author;
int subject, author2, year;
Book(String section, int subject, char author, int author2, int year) {
this.section = section;
this.subject = subject;
this.author = author;
this.author2 = author2;
this.year = year;
}
Book(char section2, float subject2, char author, int author2, int year) {
this.section2 = section2;
this.subject2 = subject2;
this.author = author;
this.author2 = author2;
this.year = year;
}
void displayData() {
System.out.println(section + subject + " ." + author + author2 + " " + year);
}
void displayData2() {
System.out.println(section2 + subject2 + " ." + author + author2 + " " + year);
}}
public class TestBook {
public static void main(String[] args) {
Book book1 = new Book("LB", 2395, "C", 65, 1991);
Book book2 = new Book("E", 185.86, "P", 277, 2010);
book1.displayData();
book2.displayData2();
s.close();
}}
Apologies for the length if it bothers. Thanks for helping in advanced!
When you call :
Book book2 = new Book("E", 185.86, "P", 277, 2010);
Change "E" to 'E' if you want to call the second constructor with char, otherwise "E" is the String object. Same thing for the field author (change "P" to 'P')
By the way, instead of creating displayData() method, you can override the toString() method :
#Override
public String toString() {
return "your string with information";
}
so you can call this method with :
System.out.println(book.toString());
System.out.println(book); // The same thing ! It will call the toString() method
Related
I am tasked with creating 5 book objects and storing in an array, which I do no problem! I am able to print out the objects' variables using println no problem but when I want be able to move the variable around using printf I dont know how to call upon a specific variable of a certain element of the array. Please Help!
public class BookReport {
public static void main(String[] args){
Book[] TheBooks = new Book[5] ;
TheBooks[0] = new Book("Gone With The Wild", "Paul Mitchell", 1000) ;
TheBooks[1] = new Book("Harry Toilet", "Donald Trump", 100) ;
TheBooks[2] = new Book("Huckles Finn Berry", "SpiderMan", 500) ;
TheBooks[3] = new Book("The Bad Habbit", "Nose Picker", 700) ;
TheBooks[4] = new Book("Alien", "Mister Green", 600) ;
System.out.printf("%10s %20s %18s \n", "Book Title" , "Author", "Pages") ;
System.out.printf("%s \n", "----------------------------------------------------") ;
//This works but I cant justify the variables to align!!!
System.out.println(TheBooks[0]) ;
}
}
public class Book {
private String title = "" ;
private String author = "" ;
private int pages = 0 ;
public Book(String title, String author, int pages){
setTitle(title) ;
setAuthor(author) ;
setPages(pages) ;
}
public String getTitle(){
return title ;
}
public String getAuthor(){
return author ;
}
public int getPages(){
return pages ;
}
public void setTitle(String newTitle){
title = newTitle ;
}
public void setAuthor(String newAuthor){
author = newAuthor ;
}
public void setPages(int newPages){
pages = newPages ;
}
public String toString(){
return title + " " + author + " " + pages ;
}
public boolean equals(Book anotherBook){
return ((title.equals(anotherBook.title)) && (author.equals (anotherBook.author)) &&
(pages == anotherBook.pages)) ;
}
}
Just call the getters for the various fields you want to print:
System.out.printf("%10s %20s %18s \n", "Book Title" , "Author", "Pages");
System.out.printf("%s \n", "----------------------------------------------------") ;
for (Book b : TheBooks) {
System.out.printf("%10s %20s %18s \n", b.getTitle(), b.getAuthor(), b.getPages());
}
By the way, you named your array of books TheBooks, but it is Java convention to not name variables with capital letters as the first letter. So theBooks would work better here.
If you want to call specific variable of a certain element of the array.
you can use
java.util.Map
for example you can make Id for all object you want to store.
HashMap<String, Book> h = new HashMap<>();
Book book = new Book("Gone With The Wild", "Paul Mitchell", 1000);
h.put(book.getTitle(), book);
book = new Book("Harry Toilet", "Donald Trump", 100);
h.put(book.getTitle(), book);
book = new Book("Huckles Finn Berry", "SpiderMan", 500);
h.put(book.getTitle(), book);
book = new Book("The Bad Habbit", "Nose Picker", 700);
h.put(book.getTitle(), book);
book = new Book("Alien", "Mister Green", 600);
h.put(book.getTitle(), book);
// if you want to call it
Book b = h.get("exampletitle);
You should also be able to use String.format() in your toString method so that you have a reusable formatted version.
#Override
public String toString(){
return String.format("%10s %20s %18s \n", title, author, pages);
}
P.s. I think it would be good practice to include hashCode() for classes where you include an equals().
I'd like to print out the name of the country and it's classification (as seen in the end of the code). However, the if-statement doesn't work. I tried putting it out of the constructor, but that doesn't work and when I try it in my main method it won't work anyway, because the variables are defined in the class Country. So I wanted to ask, how I can use this if statement to make the classification.
public class Exercise {
public static void main(String[] args){
Country Sweden = new Country("Sweden", 498000000000l,10000000);
Sweden.representcountry();
}
public static class Country{
String name;
long GDP;
int population;
int GDPCapita;
String classification;
public Country(String name, long GDP, int population){
this.name = name;
this.GDP = GDP;
this.population = population;
GDPCapita = (int) (this.GDP / this.population);
}
// Getters and Setters
/*
if(GDPCapita >= 10000){
classification = "Developed country";
}
else {
classification = "Developing country";
}
*/
final String END_OF_LINE = System.lineSeparator();
public String representcountry(){
System.out.println(this.name + ":" + END_OF_LINE // + classification
+ "Population: " + + this.population + END_OF_LINE
+ "GDP: " + this.GDP + END_OF_LINE
+ GDPCapita + " per capita");
return "";
}
}
}
You just do like this :
public Country(String name, long GDP, int population){
this.name = name;
this.GDP = GDP;
this.population = population;
GDPCapita = (int) (this.GDP / this.population);
if(GDPCapita >= 10000){
classification = "Developed country";
}else {
classification = "Developing country";
}
}
By using ternary operator you can replace the if/else, he is shorter, but you need to understand and like it, this is only a tip :
classification = GDPCapita >= 10000 ? "Developed country" : "Developing country";
Why do you use everywhere the keyword "this." except for GDPCapita and classification ?
public Country(String name, long GDP, int population){
// Getters and Setters
this.name = name;
this.GDP = GDP;
this.population = population;
this.GDPCapita = (int) (this.GDP / this.population);
if(this.GDPCapita >= 10000){
this.classification = "Developed country";
}
else {
this.classification = "Developing country";
}
}
Hi I am having some problems with my array of objects. If I assign the length of the array (of objects) to 4 it does not allow me to choose option 3 (program keeps asking for the option when I choose 3. otherwise all options works fine), if I assign it to 5 it allows me but I get null pointer exception (because the array will have an extra object with no value assign to it - null). If I print out the array just after I called the constructor. It works fine
public static void main(String[] args)
{
int menuOption = 0;
int size = 4;
BookStore[] book = new BookStore[size];
//populate the object book for testing purpose
book[0] = new BookStore("Now", "Me", "Aussie", 2014, 123456, 25.50, 2);
book[1] = new BookStore("Today", "You", "UK", 1992, 023456, 20.50, 5);
book[2] = new BookStore("Current", "Me", "Aussie", 2005, 234567, 25.00, 4);
book[3] = new BookStore("Tomorrow", "You", "UK", 1909, 523456, 20.00, 15);
//print out the array here, changing the index one by one, I wont have any error
//E.g. book[0].displayDetails();
while(menuOption !=1)
{
displayMenu(); //display a plain menu
menuOption = readOption(); //read option from users keyboard
switch(menuOption)
{
..........
case 3:
for(BookStore b: book)
{
b.displayDetails();
//if i assign the length of array to 4 does not allow to choose the option 3
//if i assign the length of array to 5 null point exception
}
break;
........
}
..............
}
}
public class BookStore
{
private String title;
private String author;
private String publisher;
private int year;
private long isbn;
private double price;
private int quantity;
public BookStore(String bTitle, String bAuthor, String bPublisher, int bYear,
long bIsbn, double bPrice, int bQty)
{
title = bTitle;
author = bAuthor;
publisher = bPublisher;
year = bYear;
isbn = bIsbn;
price = bPrice;
quantity = bQty;
}
public void displayDetails()
{
System.out.println("Title: "+title);
System.out.println("Author: "+author);
System.out.println("Publisher: "+publisher);
System.out.println("Year: "+year);
System.out.println("Isbn: "+isbn);
System.out.println("Price: "+price);
System.out.println("Quantity: "+quantity);
System.out.println("Total Value: "+getTotalValue());
System.out.println("");
}
public double getTotalValue()
{
return (double)quantity * price;
}
.........
}
I suggest you modify BookStore, change your displayDetails() and Override toString() -
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Title: "+title);
sb.append("\nAuthor: "+author);
sb.append("\nPublisher: "+publisher);
sb.append("\nYear: "+year);
sb.append("\nIsbn: "+isbn);
sb.append("\nPrice: "+price);
sb.append("\nQuantity: "+quantity);
sb.append("\nTotal Value: "+getTotalValue());
return sb.toString();
}
Then you can use
System.out.println(Arrays.toString(book));
or just
for (Book b : book) {
System.out.println(b); // <-- calls toString()
}
I am breaking my head on this problem to find a suitable data type to use, but I am not able to settle with which one would be the most efficient and simple way to program this without using any third party libraries:
Problem:
Consider Share prices for a N number of companies given for each month since year 1990 in a CSV file. Format of the file is as below with first line as header.
Year,Month,Company A, Company B,Company C, .............Company N
1990, Jan, 10, 15, 20, , ..........,50
1990, Feb, 10, 15, 20, , ..........,50
.
.
.
.
2013, Sep, 50, 10, 15............500
Output:
List for each Company year and month in which the share price was highest.
I've considered using trees, Hashmap, Lists but I am unable to finalise THE ONE solution. I am a newbie to Java with a couple of weeks of Java coding experience so far. Any help in the form of pseudo code, program or what data type to use is appreciated.
Ok, there are countless way to do this but my favorite one is to create a Company class to hold the Company.name, Company.month, Company.year, Company.price and use the Map to add the data. The adding logic would then check the map to see if a company with the same name exist, if not exist or the new company price is larger simply put the new company data to the map with company name as key. Well, the following code is just for demonstrating the purpose, I would make use eclipse to generate the getters/setters and use those instead of direct member variable just like the demo. And this demo lack the reading and collecting company data from CSV file.
CompanyLoader.java
package org.cnci.poc;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class CompanyLoader {
private List<Company> companies;
private int lastReadIdx=0;
public CompanyLoader() {
}
// Simply read the CSV and return the next set of company data
private Company getNextCompanyData() {
if (companies == null) {
lastReadIdx = 0;
try {
loadCompanies();
} catch (Exception e) {
}
}
if (companies == null) return null;
if (lastReadIdx < companies.size()) return companies.get(lastReadIdx++);
return null;
}
public void loadCompanies() throws Exception {
Scanner s = null;
try {
companies = new ArrayList<Company>();
File f = new File("test.csv");
System.out.println(f.getAbsolutePath());
s = new Scanner(new FileInputStream(f));
String[] headers = readLine(s);
System.out.println("headers: " + Arrays.toString(headers));
if (headers != null && headers.length >0) {
String[] data = null;
while ((data = readLine(s)) != null) {
System.out.println("data: " + Arrays.toString(data));
if (data.length != headers.length) {
companies = null;
throw new Exception("Invalid Data - headers count " + headers.length + " does not match with data count "+data.length);
}
String year = data[0];
String month = data[1];
for (int x=2; x<data.length; x++) {
double price = new Double(data[x]).doubleValue();
Company company = new Company(headers[x], year, month, price);
companies.add(company);
}
}
}
} finally {
if (s != null) s.close();
}
}
private String[] readLine(Scanner s) {
if (s.hasNextLine()) {
return s.nextLine().trim().split(",");
}
return null;
}
public void processCompanies() {
Map<String, Company> companies = new HashMap<String, Company>();
Company newCompany = null;
// repeat until all company data processed from CSV file
while ((newCompany = getNextCompanyData()) != null) {
Company oldCompany = companies.get(newCompany.getName());
if (oldCompany == null || newCompany.getPrice() > oldCompany.getPrice())
companies.put(newCompany.getName(), newCompany);
}
// Done, now display the winners
for (String name : companies.keySet()) {
Company company = companies.get(name);
System.out.println(company.getName() + " highest price " + company.getPrice() + " is " + company.getMonth() + " " + company.getYear());
}
}
public static void main(String[] args) {
CompanyLoader loader = new CompanyLoader();
loader.processCompanies();
}
}
Company.java
package org.cnci.poc;
public class Company {
private String name;
private String year;
private String month;
private double price;
public Company(String name, String year, String month, double price) {
super();
this.name = name;
this.year = year;
this.month = month;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
#Override
public String toString() {
return "Company [name=" + name + ", year=" + year + ", month=" + month + ", price=" + price + "]";
}
}
test.csv
Year,Month,Company A,Company B,Company C,Company D,Company N
1990, Jan, 10, 15, 20, 31, 50
1990, Feb, 11, 14, 21, 30, 51
output:
C:\Projects\Java\POC\test.csv
headers: [Year, Month, Company A, Company B, Company C, Company D, Company N]
data: [1990, Jan, 10, 15, 20, 31, 50]
data: [1990, Feb, 11, 14, 21, 30, 51]
Company B highest price 15.0 is Jan 1990
Company C highest price 21.0 is Feb 1990
Company N highest price 51.0 is Feb 1990
Company A highest price 11.0 is Feb 1990
Company D highest price 31.0 is Jan 1990
Well . you should read each line in as a String. Then, for each line after the title, you might follow one of several strategies: create an array of date, and an array of float for the stock price for each company
Or create a Company Object that itself has an array of for date and stock price)
you will need an "addDatePrice(date, price) method in the Company object. You can create the right number of companies from info in the title csv line (and give the Company object a nam)
What my program does now:
I create a person object with the following information: firstname, lastname, birthdate (the data is different class).
The date class, has four variables: day, month, year and 18+ (yes or no).
What does work: I can create a person object with a firstname, lastname and birthdate succesfully.
My person class (what looks like it works).
public class Person {
public String firstName;
public String lastName;
public Date date;
public String toString() {
return (firstName + " " + lastName + " (" + date);
}
public Person(String firstName, String lastName, Date date) {
this.firstName = firstName;
this.lastName = lastName;
this.date = date;
}
}
MY class including my main, where I also have a method where I create my person(s).
public static Person setName() {
String name;
String lastName
String inputBirthdate;
Date niceDate
Date newDate;
System.out.println("Firstname:");
firstName = userInput();
System.out.println("Lastname:");
lastName = userInput();
System.out.println("Birthday:");
inputBirthdate = userInput();
niceDate = new Date(inputBirthdate);
newDate = new Date(niceDate);
return new Gast(firstName, lastName, newDate);
}
And then I have my Date class, where I check if the input of the date is correct. Please not that I can get my Date class to work correctly WITHOUT the 4th variable.
public class Date {
public String day;
public String month;
public String year;
public boolean child;
public String toString() {
return (day + "." + month + "." + year + "." + child);
}
/*Date(String day, String month, String year, boolean child) {
this.day = dag;
this.month = month;
this.year = year;
this.child = child;
}*/ //don't need this one, output is the same
public Date(Datum niceDate) {
int bYear = Integer.parseInt(niceDate.year;
int bMonth = Integer.parseInt(niceDate.day);
int bDay = Integer.parseInt(niceDate.day);
boolean child = false;
if (bYear > 1995) {
this.child= true;
} else if (bYear == 1995 && bMonth > 10) {
this.child = true;
} else if (bYear == 1995 && bMonth == 10 && bDay > 1) {
this.child = true;
} else {
this.child = false;
}
}
public Date(String birthdate) {
String patroon = "\\d{2}-\\d{2}-\\d{4}";
boolean b = birthdate.matches(patroon);
if (b) {
String[] str = birthdate.split("-");
for (String s: str)
this.day = str[0];
this.month = str[1];
this.year = str[2];
}
else {
System.out.println("Birthday is formatted wrong");
}
}
}
If I run this (witch the check of adult or not (the check looks like it work!), However, my input of the birthdate returns null:
Room 1: Name name (null.null.null)false //boolean works, date not
Room 2: available
I think the problem is that in my second method in my Date class, the public Date(Date Nicedate) deletes my date after parsing it to an int.
So basically I only want to return the Boolean and keep my Strings exactly the same, and only editing them for using them as an Int for the calculations.
Can someone point me in the right direction? Probably it's a very simple solution, but I've been working on it all day and don't see the solution.
EDIT AS REQUESTED: (I've the this statements in the public Date(datum niceDate) but the date still won't show. Hmmmmm:
public Date(Datum niceDate) {
this.year = year;
this.day = day;
this.month = month;
int bYear = Integer.parseInt(niceDate.year;
int bMonth = Integer.parseInt(niceDate.day);
int bDay = Integer.parseInt(niceDate.day);
boolean child = false;
if (bYear > 1995) {
this.child= true;
} else if (bYear == 1995 && bMonth > 10) {
this.child = true;
} else if (bYear == 1995 && bMonth == 10 && bDay > 1) {
this.child = true;
} else {
this.child = false;
}
}
public Date(String birthdate) {
String patroon = "\\d{2}-\\d{2}-\\d{4}";
boolean b = birthdate.matches(patroon);
if (b) {
String[] str = birthdate.split("-");
for (String s: str)
this.day = str[0];
this.month = str[1];
this.year = str[2];
}
else {
System.out.println("Birthday is formatted wrong");
}
}
}
The problem is that when you create newDate from niceDate, you are not copying the day/month/year.
If you look in your public Date(Datum niceDate) constructor, the only instance variable that you set is this.child, but you also need to set this.day, this.month, and this.year.
Also, I recommend you instead create a function for the date calculation called isAdult as a method of your Date class, and just call niceDate.isAdult() if you need to show whether the date is 18+ years ago. Otherwise, it's easy to make a mistake and have this.child be incorrect.
public Date(Datum niceDate) {
this.year = year;
In this constructor, this.year and year refer to the same member variable. So you are assigning the value of that variable to itself.
Then later you do
int bYear = Integer.parseInt(niceDate.year);
which parses the value from niceDate and assigns its value to a local variable named bYear. Instead, you need to assign the result of parseInt to this.year:
this.year = Integer.parseInt(niceDate.year);
You can make similar changes to all of the other variables.