How to access variable of an object in an array? - java

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().

Related

How to get one specific variable from an ArrayList which built for containing many variables?

I have a class named Country. There is 2 Strings named "name" and "code" in Country class.
I made a constructor that includes both of them.
In main, I build up a Country with name "germany" and for name parameter,I enter "Germany" and for code, I enter "GER".
I also made an ArrayList called countries that works with the type "Country" and I've added germany in it.
So the question is, how can I call name parameter in that ArrayList?
ArrayList does not have a direct method to get the object by the value of its properties, however it allows to retrieve objects by index using method get(int i) or by iterating and comparing the value.
Country germany = new Country("Germany", "GER");
List<Country> countries = new ArrayList<>();
countries.add(germany);
// use index
for (int i = 0, n = countries.size(); i < n; i++) {
if (countries.get(i).getName().equals("Germany")) {
System.out.println("Found!");
}
}
// iterate by index
for (Country country : countries) {
if (country.getName().equals("Germany")) {
System.out.println("Found!");
}
}
// use Stream API filter
countries.stream()
.filter(country -> country.getName().equals("Germany"))
.forEach(country -> System.out.println("Found!"));
If you need to look up the counties by name directly, a map Map<String, Country> should be used instead:
Map<String, Country> countryDictionary = new HashMap<>();
countryDictionary.put("Germany", germany);
countryDictionary.get("Germany"); // returns appropriate country or null
You have he class Country with the appropriate constructor to instantiate an complete instance of a Country object. What you want is an ArrayList (or List) of Country, for example,
List<Country> countries = new ArrayList<>();
Now, to fill the ArrayList with instances of Country you can do:
countries.add(new Country("Germany", "GER"));
countries.add(new Country("Sweden", "SWE"));
countries.add(new Country("Canada", "CAN"));
countries.add(new Country("United States of America", "USA"));
To get the ISO3 code from a supplied country name you might do:
List<Country> countries = new ArrayList<>();
countries.add(new Country("Germany", "GER"));
countries.add(new Country("Sweden", "SWE"));
countries.add(new Country("Canada", "CAN"));
countries.add(new Country("United States", "USA"));
Scanner input = new Scanner(System.in);
// Get country code from country name:
String country = "";
while(country.isEmpty()) {
System.out.println("Enter a Country name or 'n' for next example:");
System.out.print("Country: --> " );
country = input.nextLine().trim();
if (country.equalsIgnoreCase("n")) {
break; // Break out of current while loop
}
if (!country.matches("(?i)[a-z]+")) {
System.out.println("Invalid Entry! Try again...\n");
}
else {
for (Country cntry : countries) {
String ctry = cntry.getName();
if (ctry.equalsIgnoreCase(country)) {
System.out.println("Country Code for " + ctry + " is: --> " + cntry.getCode());
System.out.println("The List contains: --> " + cntry.toString());
break; // Break out of loop;
}
}
}
country = "";
System.out.println();
}
System.out.println();
// Get Country Name from Country Code:
String code = "";
while(code.isEmpty()) {
System.out.println("Enter a Country Code or 'n' for next example:");
System.out.print("Code: --> " );
code = input.nextLine().trim().toUpperCase();
if (code.equalsIgnoreCase("n")) {
break; // Break out of current while loop
}
if (!code.matches("(?i)[a-z]{3}")) {
System.out.println("Invalid Entry! Try again...\n");
}
else {
for (Country cntry : countries) {
if (cntry.getCode().equalsIgnoreCase(code)) {
System.out.println("Country Name for " + code + " is: --> " + cntry.getName());
System.out.println("The List contains: --> " + cntry.toString());
break; // Break out of loop;
}
}
}
code = "";
System.out.println();
}
// Print the whole list:
System.out.println("\n The whole list:\n ===============");
for (Country cntry : countries) {
System.out.println(cntry.toString());
}
This of course assumes the Country class is something like this:
public class Country {
private String name;
private String code;
public Country(String name, String code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return String.format("%-15s %-5s", name, code);
}
}
All in all however, I think it's just easier to utilize the java.util.Locale class to get this information, for example:
public static String getISO3CountryCode(String countryName) {
String countryCode = null;
String[] isoCountries = java.util.Locale.getISOCountries();
for (String country : isoCountries) {
java.util.Locale locale = new java.util.Locale("en", country);
String iso3 = locale.getISO3Country();
String name = locale.getDisplayCountry();
if (name.equalsIgnoreCase(countryName)) {
countryCode = iso3;
}
}
return countryCode;
}
A way you might use this method:
System.out.println(getISO3CountryCode("Australia"));
or
String code = getISO3CountryCode("Australia")
This would ultimately supply you with the ISO-Alpha3 code of AUS. If you want the ISO-Alpha2 code (AU) then you would change the method code line of:
String iso = locale.getISO3Country();
with:
String iso = locale.getCountry();
If you want a list of all country codes...well I think you know what to do.

Java Error: The constructor is undefined (2)

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

Formatting: String cannot be converted to String[]

Using the data array, create instances of books and store them in a one-dimensional array of Book, called bookArray. Using the quantity array, walk through the book array and calculate the total charge per book sold. Print in a dialog box the book title, the book isbn, and the total charge for each book. Then, print the grand total of all books sold.
So far I have done this, but I'm having issue with the JOptionPane and formatting.
Error
$ javac BookTest.java
BookTest.java:41: error: incompatible types: String cannot be converted to String[][]
dataArray +=String.format(" %s, %s ", b.getTitle(), b.getIsbn());
^
1 error
And the code:
import javax.swing.JOptionPane;
public class BookTest {
public static void main(String args[]) {
String dataArray [][]=
{{ "Fiction", "Abraham Lincoln Vampire Hunter", "Grahame-Smith", "Wiley", "NY", "978-0446563079", "13.99", "222"},
{"Fiction", "Frankenstein", "Shelley", "Prescott", "GA", "978-0486282114", "7.99", "321"},
{"NonFiction", "Life of Kennedy", "Jones", "Pearson", "MT", "758-29304566", "12.90", "biography"},
{"Fiction", "Dracula", "Stoker", "Addison", "CA", "978-0486411095","5.99", "145"},
{"Fiction", "Curse of the Wolfman", "Hageman", "Wesley", "MA", "B00381AKHG", "10.59", "876"},
{"NonFiction", "How to Pass Java", "Willis", "Wiley"," NY", "444-395869790", "1.99", "technology"},
{"Fiction", "The Mummy", "Rice", "Addision", "CA", "978-0345369949", "7.99", "954"},
{"NonFiction", "History of Texas", "Smith", "Prescott", "CA", "123-683947687", "9.75", "history"}
};
Book bookArray[] = new Book [8];
for (int i = 0; i < bookArray.length; i++) {
if (dataArray[i][0].equals("Fiction")) {
Publisher p = new Publisher(dataArray[i][3], dataArray[i][4]);
bookArray[i] = new Fiction(dataArray[i][1], dataArray[i][2], dataArray[i][5],
p, Double.parseDouble(dataArray[i][6]), dataArray[i][7]);
} else {
Publisher p = new Publisher(dataArray[i][3], dataArray[i][4]);
bookArray[i] = new NonFiction(dataArray[i][1], dataArray[i][2], dataArray[i][5],
p, Double.parseDouble(dataArray[i][6]), dataArray[i][7]);
}
}
for (Book b:bookArray) {
dataArray +=String.format(" %s, %s ", b.getTitle(), b.getIsbn());
JOptionPane.showMessageDialog(null, dataArray);
}
}
}
Don't use your dataArray to output things in the message box. Use a String variable.
for (Book b : bookArray) {
String bookOutput = String.format(" %s, %s ", b.getTitle(), b.getIsbn());
JOptionPane.showMessageDialog(null, bookOutput);
}
Even better, add a toString() to your Book class that returns String.format(" %s, %s ", getTitle(), getIsbn()) and then do your loop like this:
for (Book b : bookArray) {
JOptionPane.showMessageDialog(null, b.toString());
}
However, if you want to output the price for each book and then the total, your loop will look more like this:
double totalPrice = 0.0;
for (int i = 0; i < bookArray.length; i++) { //can't use foreach because of use of parallel arrays bookArray & quantityArray
Book b = bookArray[i];
double price = b.getPrice() * quantityArray[i];
totalPrice += price;
String bookStr = String.format(" %s, %s %s", b.getTitle(), b.getIsbn(),
DecimalFormat.getCurrencyInstance().format(price));
JOptionPane.showMessageDialog(null, bookStr);
}
String totalStr = String.format("Total Charge: %s",
DecimalFormat.getCurrencyInstance().format(totalPrice)));
JOptionPane.showMessageDialog(null, totalStr);
String.format returns a String as per the docs. You are trying to concatenate a String to a 2d array.
dataArray +=String.format(" %s, %s ", b.getTitle(), b.getIsbn());
In the above line you probably want to access a location from the 2d array, like dataArray[0][0] and then do the concatenation. Something like:
dataArray[0][0] +=String.format(" %s, %s ", b.getTitle(), b.getIsbn());

Java Loop issue Object null exception or menu does not work

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()
}

Java Repeated output from nested for loop [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I created this package, and the problem is when is runs it repeats the same catalog entries between bins.
I think the problem is in the detailedInventory method.
SHOULD BE: It should create a new random bin item (type, title, artist) for Bin B, not use the same element from Bin A. Other than this, the output is correct. SKU numbers are correctly generated and displayed.
**The values of i, when they correspond to the catalog, are objects. they are actually different types of physical media, such as DVDs or cassettes, with title, artist and SKU attributes.
***Although it does not seem to make sense, the data should be generated randomly. (This class is part of a larger concept/lesson to illustrate inheritance.)
Any help would be greatly appreciated!
Here is the output I see:
Bin A:
DVD - Greatest Hits Volume 2 (Limp Bizkit), SKU 1234-0: 500
Cassette - The Best Of (Michael Jackson), SKU 1234-1: 25
DVD - Love Songs (Michael Jackson), SKU 1234-2: 7720
Bin B:
DVD - Greatest Hits Volume 2 (Limp Bizkit), SKU 1234-3: 1000
The bin item under Bin B should not be the same as A.
public class testMusicMedia
{
public static ArrayList<MusicMedia> MakeMusicCatalog( int size )
{
String[] titles =
{
"Greatest Hits Volume 1", "Greatest Hits Volume 2",
"The Best Of", "Love Songs",
"The Early Years", "The Later Years"
};
String[] artists =
{
"Michael Jackson", "Eminem",
"The Beatles", "Shania Twain",
"Limp Bizkit"
};
ArrayList<MusicMedia> catalog = new ArrayList<MusicMedia>();
Random rn = new Random();
for ( int i = 0 ; i < size ; i++ )
{
MusicMedia m;
int mediatype = rn.nextInt( 3 );
String title = titles[ rn.nextInt( titles.length ) ];
String artist = artists[ rn.nextInt( artists.length ) ];
String sku = "1234-" + i;
if ( mediatype == 0 )
m = new CompactDisk( title, artist, sku );
else if ( mediatype == 1 )
m = new DigitalVideoDisk( title, artist, sku );
else
m = new CassetteTape( title, artist, sku );
catalog.add( m );
}
return catalog;
}
public static String lookupMedia( ArrayList<MusicMedia> catalog,
String sku )
{
for ( MusicMedia m : catalog )
{
if ( m.getSKU().equals( sku ))
return "SKU is in catalog";
}
return "SKU not in catalog";
}
public static String detailedInventory( ArrayList<MusicMedia> catalog, ArrayList<Bin> warehouse )
{
String s = "";
for ( Bin bn : warehouse ){
s += "Bin " + bn.getName() + ":\n";
for (int i = 0; i < bn.getContents().size(); i++){
s += catalog.get(i) + ", " + bn.getContents().get(i) + "\n";
}
}
s += "\n";
return s;
}
public static void main( String[] args )
{
ArrayList<MusicMedia> catalog = MakeMusicCatalog( 10 );
ArrayList<Bin> warehouse = new ArrayList<Bin>();
Bin a = new Bin( "A" );
Bin b = new Bin( "B" );
warehouse.add( a );
warehouse.add( b );
a.add( new BinItem( "1234-0", 500 ) );
a.add( new BinItem( "1234-1", 25 ) );
a.add( new BinItem( "1234-2", 7720 ) );
b.add( new BinItem( "1234-3", 1000 ) );
System.out.println( detailedInventory( catalog, warehouse ) );
}
}
I call the collection of all the items in a bin that share the same SKU a “bin item”. Each object of the Bin class (not shown) represents a bin in a pretend warehouse. A Bin object has two instance variables: a String that contains the bin name and an ArrayList that contains a BinItem for each of the SKUs stored in the bin. The toString method of the Bin class uses the toString method of the BinItem class. It generates lists that only involve SKUs and quantities.
This method should use a for-each loop to cycle thorugh all the bins in the warehouse. For each bin, s should be extended by the String "Bin " followed by the name of the bin, followed by a colon and \n to start new line. Then it should cycle through all the bin items in the current bin, for each one
extending s by a new line of text that begins with the result of looking up the current bin item’s SKU in the input catalog, and continue with a comma followed by the String representation of the bin item.
The output should look something like this:
Bin A:
CD - The Later Years (Shania Twain), SKU 1234-0: 500
Cassette - Greatest Hits Volume 2 (The Beatles), SKU 1234-1: 25
Cassette - Greatest Hits Volume 1 (Shania Twain), SKU 1234-2: 7720
Bin B:
Cassette - Greatest Hits Volume 2 (Michael Jackson), SKU 1234-3: 1000
Full code:
public class MusicMedia
{
private String myTitle,
myArtist,
mySKU;
public MusicMedia( String title, String artist, String sku )
{
myTitle = title;
myArtist = artist;
mySKU = sku;
}
public String getTitle()
{
return myTitle;
}
public String getArtist()
{
return myArtist;
}
public String getMediaType()
{
return "Unknown";
}
public String getSKU()
{
return mySKU;
}
public String toString()
{
return " - " + getTitle() + " (" + getArtist() + ")";
}
}
public class Disk extends MusicMedia
{
/**
* Constructor for objects of class Disk
*/
public Disk( String title, String artist, String sku )
{
super(title, artist, sku);
}
public String getMediaType()
{
return "Disk";
}
public String toString()
{
return getMediaType() + super.toString();
}
}
I also have an identical CassetteTape class that also extends MusicMedia. Also two other subclasses of Disk, called CompactDisk and DigitalVideoDisk. These two are also almost identical to each other, so I have pasted the DVD class below.
public class DigitalVideoDisk extends Disk
{
/**
* Constructor for objects of class DigitalVideoDisk
*/
public DigitalVideoDisk( String title, String artist, String sku )
{
super(title, artist, sku);
}
public String getMediaType()
{
return "DVD";
}
}
public class BinItem
{
private String mySKU;
private int myQuantity;
public BinItem( String sku, int quantity )
{
mySKU = sku;
myQuantity = quantity;
}
public String getSKU()
{
return mySKU;
}
public int getQuantity()
{
return myQuantity;
}
public String toString()
{
return "SKU " + getSKU() + ": " + getQuantity();
}
}
public class Bin
{
private String myName; //bin name
private ArrayList<BinItem> myContents; //contains a binItem
public Bin( String name )
{
myName = name;
myContents = new ArrayList<BinItem>();
}
public String getName()
{
return myName;
}
public ArrayList<BinItem> getContents()
{
return myContents;
}
public void add( BinItem b )
{
myContents.add( b );
}
public String toString()
{
String s = "Bin " + myName + ":\n";
for ( BinItem b : myContents )
s += b + "\n";
return s;
}
}
Ok, per your edit:
...the result of looking up the current bin item’s SKU in the input catalog...
You aren't doing this right now and it was the key point that we needed to understand what the program was supposed to do. Right now you're just retrieving an element from catalog using i, basically arbitrarily.
So the first thing you need to do is create a helper method that searches catalog for a MusicMedia object of a certain SKU. You have a method very much like it called lookupMedia so I've just modified it to this slightly different specification. This returns m instead of a String value:
public static MusicMedia getMediaBySKU(
ArrayList<MusicMedia> catalog, String sku
) {
for ( MusicMedia m : catalog ) {
if ( m.getSKU().equals(sku) )
return m;
}
return null;
}
Now that you are able to retrieve an item based on the SKU you can modify the detailedInventory loop to use it:
for ( Bin bn : warehouse ){
s += "Bin " + bn.getName() + ":\n";
for ( BinItem item : bn.getContents() ){
MusicMedia mm = getMediaBySKU(catalog, item.getSKU());
s += mm + ", " + item + "\n";
}
}
(Not sure how to get the SKU from the BinItem so I guessed but I hope you get the idea. If you don't have a method that returns the SKU already, you probably need to make one.)

Categories