I'm relatively new to the Java language and have a project I'm doing for school in which I have a Book class that has the normal setters/getters, constructors, and overrides for this class, nothing complicated. I have to change it so I can get multiple authors by utilizing Set and HashSet. The question I have is how would I go about doing this? So far, and correct me if I'm wrong, I have this
import java.util.*;
public class Book{
private Set<String> authorSet;
private String isbn;
public Book(){
authorSet = null;
isbn = null;
}
public Book(String isbn, Set<String> authorSet){
this.isbn = isbn;
Set<String> s = new HashSet<String>();
// Do I do anything else here?
}
public String getIsbn(){
return isbn;
}
public void setIsnb(String isbn){
this.isbn = isbn;
}
public Set<String> getAuthorSet(Set<String> newAuthorSet{
return newAuthorSet;
}
public void setAuthorSet(Set<String> newAuthorSet){
this.authorSet = newAuthorSet;
}
Before moving on to the overrides, I want to make sure I get this properly. I've tried to look for similar examples so I can see what's going on, but I haven't had much luck as of yet. I'm sure it's very simple, but I'm just starting to learn the language. Thanks for the help
First of all, in your default constructor, get rid of
authorSet = null;
and instead initialize your authorSet variable to a new HashSet. The reason for this is that you want to create the authorSet container regardless of whether any authors are added to begin with.
You'll probably want a constructor that takes just an isbn String. Also consider a constructor that takes isbn String and a variable number of Author Strings.
Ah, I missed this:
public Book(String isbn, Set<String> authorSet){
this.isbn = isbn;
Set<String> s = new HashSet<String>();
// Do I do anything else here?
}
Not good as you ignore both the parameter and the field! Instead, assign the set parameter to the existing field as you would with any other field.
public Book(String isbn, Set<String> authorSet){
this.isbn = isbn;
this.authorSet = authorSet;
}
Then give your class an addAuthor(String author) method. Better for you to code this since this is homework. I really don't think that there's a whole lot more that you need with regards to this problem.
I'd have taken away the default constructor. Also, why would you need to set the authorSet? Wouldn't it better to just add and remove from it? Also why would you need to set the isbn. Could you instead just take it in the constructor, as I don't think you'd ever have to change it. How about something like this?
import java.util.HashSet;
import java.util.Set;
public class Book {
private final Set<String> authorSet;
private final String isbn;
public Book(String isbn) {
this.isbn = isbn;
this.authorSet = new HashSet<>();
}
public String getIsbn() {
return isbn;
}
public Set<String> getAuthorSet() {
return authorSet;
}
public void addAuthor(String author) {
authorSet.add(author);
}
public void removeAuthor(String author) {
authorSet.remove(author);
}
}
For extra points, the practice of returning your actual collection (set) implementation can allow a caller to muck with your internals. Thus, this is a little hazardous:
public Set<String> getAuthorSet() {
return authorSet;
}
safer:
public Set<String> getAuthorSet() {
return Collections.unmodifiableSet(authorSet);
}
Similarly if you had need to accept a new set in your API, but did not want to trust the caller to not later violate your representation, then you might do this:
public void setAuthorSet(Set<String> newAuthorSet) {
authorSet = new HashSet<String>(newAuthorSet);
}
Related
My BookTester class is creating a new book and calling getAuthor(), but when I run, it doesn't return any output. I'm not sure why? Any help is appreciated, thanks!
public class BookTester {
public static void main(String[] args) {
Book myBook = new Book("My life", "Sam Daily", 2001);
myBook.getAuthor();
}
}
class Book {
private String title;
private String author;
private int publishedYear;
public Book(String title, String author, int year)
{
this.title = title;
this.author = author;
publishedYear = year;
}
public int getYear(){
System.out.println(publishedYear);
return publishedYear;
}
public String getTitle(){
return title;
}
public String getAuthor(){
return author;
}
}
The method signature:
public String getAuthor(){ ... }
represents a method that takes no parameters and returns a String. even the name of the method speaks it "getAuthor", to get or retrieve something.
and you're ignoring the result of the method call.
the solution is either store the result to a variable and then operate on it.
String author = myBook.getAuthor();
or if you want to print to the console then you can do:
System.out.println(myBook.getAuthor());
Reason why you don't see returned value is because you are ignoring it.
public static void main(String[] args) {
Book myBook = new Book("My life", "Sam Daily", 2001);
myBook.getAuthor(); // Value is returned but not used
}
Instead you could assign returned value to variable and print it or just print it from method call:
System.out.println(myBook.getAuthor());
Considering that this is really basic thing I suggest you to get some good Java book or some tutorial in other to advance faster.
The method getAuthor() effectivly returns something, but you did not use it
You can store it to use after :
String author = myBook.getAuthor();
System.out.println(author); // for simple printing
System.out.println(author.charAt(1)); // to print a single char
...
You can print it directly
System.out.println("The author is "+ myBook.getAuthor());
First receive method result in string variable and print it..
string result=myBook.getAuthor();
system.out.println(result);
I have cut out the code to shorten the page but I'm asking how do I change personInterests into its own class. Apologies for the vague question but essentially I want to change personInterests in my Person class to a class where personInterests has multiple variables.
import java.util.ArrayList;
import java.util.*;
public class Person{
private String personName;
private String[] personInterests = new String[3];
public Person(String personName, String[] personInterests){
this.personName = personName;
this.personInterests = personInterests;
}
public void setInterests(String[] personInterests){
this.personInterests = personInterests;
}
public String[] getInterests(){
return personInterests;
}
public String getName(){
return personName;
}
public String toString(){
String result = getName() + " ";
for (String interests : personInterests) {
result += interests + " ";
}
return result;
}
}
This was my idea of how it would work just not sure how I would use this class and call it later on.
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
private String interestName;
private ArrayList<Interests> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterests(Interests p){
interestsList.add(p);
}
Interests getInterests(int i){
return interestsList.get(i);
}
}
Any help is appreciated, as I said this code has mostly been taken out and this was an old project already completed just wanted to see if I could change some of the features.
OK so here's what I would do to clean this up for you and make it work. Firstly, think about what you are trying to do. You want to create a Person who has multiple Interests, right? So the Interest class, going by your above example, can be changed to be a typical Java object class as follows:
public class Interest {
private int dangerRating;
private String name;
public Interest (int dangerRating, String name) {
this.dangerRating = dangerRating;
this.name = name;
}
public int getDangerRating() {
return dangerRating;
}
public String getName() {
return name;
}
}
So now we've an Interest class set up where you can set a name for your interest and a danger rating. What we need to do, now, is edit your Person class so as you can store a list of interests for each Person you create.
import java.util.ArrayList;
public class Person{
private String name;
private ArrayList<Interest> interests = new ArrayList<Interest>();
public Person(String name, ArrayList<Interest> interests) {
this.name = name;
this.interests = interests;
}
public void addInterest(Interest newInterest) {
interests.add(newInterest);
}
public Interest getInterest(int indexOfInterest) {
return interests.get(indexOfInterest);
}
public ArrayList<Interest> getInterests() {
return interests;
}
public String getName() {
return name;
}
public String toString() {
String result = getName() + " ";
for(Interest interest : interests) {
result += interest.getName() + "(" + interest.getDangerRating() + ")" + " ";
}
return result.trim();
}
}
This allows you to set an initial list of all interests for your new Person and, from there, you can add new interests, get all interests or get any individual interest.
Hope this helps to clarify for you how this should all fit together!
So now it's time to instantiate everything. Lets create some Interestobjects which we will use:
Interest golf = new Interest(1, "golf");
Interest swimming = new Interest(3, "swimming");
Now lets assume we want two people called John and Mary. John likes golf and swimming while Mary only likes swimming. We'd then create their list of Interest as follows:
ArrayList<Interest> johnsInterests = new ArrayList<Interest>();
johnsInterests.add(golf);
johnsInterests.add(swimming);
ArrayList<Interest> marysInterests = new ArrayList<Interest>();
marysInterests.add(swimming);
And finally, we'd then create our two Person objects which will include the persons name and interests list.
Person john = new Person("John", johnsInterests);
Person mary = new Person("Mary", marysInterests);
And voila!
First, make an Interestclass:
public class Interest {
private int interestDangerRating;
private String interestName;
// .. getters and setters
}
then in the Personclass get rid of private String[] personInterests = new String[3];
and replace it by:
private ArrayList<Interest> interestsList = new ArrayList<>();
You're getting there with the logic of your Interests class, but it needs a few changes
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
// Is this a unique name for the entire class? If yes then no worries, but if not
// then its not needed, you've already got a list of interest names below
private String interestName;
// Change the array list to hold Strings, it's a list of words
private ArrayList<String> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterest(String p){ // Again, change this to String
interestsList.add(p);
}
String getInterest(int i){ // Change this to return a String, since we changed the ArrayList above
return interestsList.get(i);
}
}
There's alot more you need to think about with this class too. How do you know how many interests are in the list, should there be a length variable? Or what about a method that returns the entire list of interests rather than just 1?
Also, there's only one interestDangerRating being set in this class; if each interest has a different danger rating, should't you be adding a danger rating for every interest?
In terms of accessing your new class, you'll need to create a class in your code by:
Interests variableName = new Interests(1, "football");
I have randomly chosen '1' and 'football' above, since they are in your Interest class' constructor. The way your class is built, you cannot use it without providing an int and a String when the object is made
Finally, to call methods on your class, you use the variable created above to call its methods:
variableName.addInterest("basketball");
String interest = variableName.getInterest(1);
If you're struggling, I recommend looking at a simple java tutorial online. instatiating java classes and calling their methods like this are fundamental concepts in Java :)
The Following program prints
one|two
one|two
when HashSet is used. If I change it to TreeSet it prints only
one|two
Is it not expected to give the same result with the same set of data ?What am I doing wrong here? What in the program makes the second record duplicate in case of TreeSet?
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String arg[]) {
Set<Bk> bookList = new HashSet<Bk>();
//Set<Bk> bookList = new TreeSet<Bk>();
bookList.add(new Bk("one","two"));
bookList.add(new Bk("one","two"));
for(Bk book: bookList){
System.out.println(book);
}
}
}
class Bk implements Comparable<Bk> {
public String name;
public String author;
public String toString(){
return name+"|"+ author;
}
Bk(String name, String author) {
this.name = name;
this.author = author;
}
#Override
public int compareTo(Bk that) {
int author = this.author.compareTo(that.author);
int name = 0;
if (author == 0) {
name = this.name.compareTo(that.name);
return name;
} else {
return author;
}
}
}
The HashSet class will use hashCode and equals to determine if there is a duplicate already in the set. The TreeSet class will use the fact that it's Comparable (or alternatively, a Comparator) to order items and determine if there's a duplicate.
You have Bk as Comparable<Bk>, so TreeSet will work properly with it. But, you still need to override hashCode and equals so HashSet will work properly with it also.
If you want consistent behaviour with a HashSet you would have to implement hashCode() and equals(), as per the Javadoc, and in such a way as to be consistent with your compareTo() method.
short question. Hopefully it gets answered pretty fast. Lets say I have a singleton like this:
package main.library;
public enum LibrarySingleton {
INSTANCE(new String[][]{});
final String[][] bookStore;
private LibrarySingleton(String[][] bookStore){
this.bookStore = bookStore;
}
}
and a Book class that holds 3 variables:
package main.library;
public class Book{
String author;
String title;
int pages;
#Override public String toString(){
return ("|" + author + "|" + title + "|" + pages + "|");
}
public Book(){
System.out.println("Error: No book information specified");
}
public Book(String author, String title, int pages){
this.author = author;
this.title = title;
this.pages = pages;
}
public String getAuthor(){
return author;
}
public String getTitle(){
return title;
}
public int getPages(){
return pages;
}
}
I'm looking on how to use that singleton as an array holding books. How can I access the books, throw them into the array (singleton), or remove them from the array (singleton)? In case the singleton should be written differently, please correct me, and explain why is it wrong, as I'm not so "premium" with Java yet.
Really hope you guys are going to answer me on that. Just the questions please.
If you want singleton, you can use following approach:
public class Library {
private static final Library instance = new Library();
private List<Book> books = new ArrayList<Book>();
public static Library getInstance() {
return instance ;
}
public void add(Book book) {
books.add(book);
}
}
Of course, add synchronization if your program has multiple threads. And if your program runs in J2EE environment, where complex classloading occurs, you need a different pattern.
If you initialize an empty array and make it final it will stay empty and you cannot reinitialize it. I guess what you need is an arraylist (list in general). That one you can initialize and add element to it.
I am trying to print the first element on the two arrays in my Athlete class, country and name. I also need to create a object that simulates three dive attemps an athlete had (that is initially set to zero). I am new to OOP and I dont know how to go abouts doing this in my main... as far as constructors go. This is what i have done so far...
this is the main:
import java.util.Random;
import java.util.List;
public class Assignment1 {
public static void main(String[] args) {
Athlete art = new Athlete(name[0], country[0], performance[0]);
}
}
I just really am not sure what to do...
And this is the class with the arrays.
import java.util.Random;
import java.util.List;
public class Athlete {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germant", "USA"};
//Here i would like to create something that would be representing 3 dive attemps (that relate to dive and score. eventually.)
Athlete(String[] name, String[] country, Performance[] performance) {
this.name = name;
this.country=country;
this.performance=performance;
}
public Performance Perform(Dive dive){
dive.getDiveName();
return null;
}
public String[] getName() {
return name;
}
public void setName(String[] name) {
this.name = name;
}
public String[] getCountry() {
return country;
}
public void setCountry(String[] country) {
this.country = country;
}
}
thanks in advance for any help and input!
btw there is other classes too, just not relevant atm..
First, as for your Athlete class, you can remove your Getter and Setter methods since you have declared your instance variables with an access modifier of public. You can access the variables via <ClassName>.<variableName>.
However, if you really want to use that Getter and Setter, change the public modifier to private instead.
Second, for the constructor, you're trying to do a simple technique called shadowing. Shadowing is when you have a method having a parameter with the same name as the declared variable. This is an example of shadowing:
----------Shadowing sample----------
You have the following class:
public String name;
public Person(String name){
this.name = name; // This is Shadowing
}
In your main method for example, you instantiate the Person class as follow:
Person person = new Person("theolc");
Variable name will be equal to "theolc".
----------End of shadowing----------
Let's go back to your question, if you just want to print the first element with your current code, you may remove the Getter and Setter. Remove your parameters on your constructor.
public class Athlete {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germany", "USA"};
public Athlete() {
}
In your main method, you could do this.
public static void main(String[] args) {
Athlete art = new Athlete();
System.out.println(art.name[0]);
System.out.println(art.country[0]);
}
}
Currently you can't access the arrays named name and country, because they are member variables of your Athelete class.
Based on what it looks like you're trying to do, this will not work.
These arrays belong in your main class.
Your attempt at an athlete class seems to be dealing with a group of athletes, which is a design fault.
Define a class to represent a single athlete, with fields that represent the athlete's attributes:
public class Athlete {
private final String name;
private final String country;
private List<Performance> performances = new ArrayList<Performance>();
// other fields as required
public Athlete (String name, String country) {
this.name = name;
this.country = country;
}
// getters omitted
public List<Performance> getPerformances() {
return performances;
}
public Performance perform(Dive dive) {
// not sure what your intention is here, but something like this:
Performance p = new Performance(dive, this);
// add new performance to list
performances.add(p);
return p;
}
}
Then your main method would use ti like this:
public class Assignment1 {
public static void main(String[] args) {
String[] name = {"Art", "Dan", "Jen"};
String[] country = {"Canada", "Germant", "USA"};
Dive[] dive = new Dive[]{new Dive("somersault"), new Dive("foo"), new Dive("bar")};
for (int i = 0; i < name.length; i++) {
Athlete athlete = new Athlete(name[i], country[i]);
Performance performance = athlete.perform(dive[i]);
// do something with athlete and/or performance
}
}
}
I think you are a little messed up with what you doing.
Athlete is an object, athlete has a name, i has a city where he lives.
Athlete can dive.
public class Athlete {
private String name;
private String city;
public Athlete (String name, String city){
this.name = name;
this.city = city;
}
--create method dive, (i am not sure what exactly i has to do)
public void dive (){}
}
public class Main{
public static void main (String [] args){
String name = in.next(); //enter name from keyboad
String city = in.next(); //enter city form keybord
--create a new object athlete and pass paramenters name and city into the object
Athlete a = new Athlete (name, city);
}
}
public static void main(String[] args) {
public String[] name = {"Art", "Dan", "Jen"};
public String[] country = {"Canada", "Germant", "USA"};
// initialize your performance array here too.
//Your constructor takes arrays as an argument so you need to be sure to pass in the arrays and not just objects.
Athlete art = new Athlete(name, country, performance);
}
First off, the arrays are pointless, let's get rid of them: all they are doing is providing values for mock data. How you construct mock objects has been debated ad nauseum, but clearly, the code to create the fake Athletes should be inside of a unit test. I would use Joshua Bloch's static builder for the Athlete class, but you only have two attributes right now, so just pass those in a Constructor. Would look like this:
class Athlete {
private String name;
private String country;
private List<Dive> dives;
public Athlete(String name, String country){
this.name = name;
this.country = country;
}
public String getName(){
return this.name;
}
public String getCountry(){
return this.country;
}
public String getDives(){
return this.dives;
}
public void addDive(Dive dive){
this.dives.add(dive);
}
}
Then for the Dive class:
class Dive {
private Athlete athlete;
private Date date;
private double score;
public Dive(Athlete athlete, double score){
this.athlete = athlete;
this.score = score;
this.date = new Date();
}
public Athlete getAthlete(){
return this.athlete;
}
public Athlete getAthlete(){
return this.athlete;
}
public Athlete getAthlete(){
return this.athlete;
}
}
Then make a unit test and just construct the classes, and manipulate them, make sure that they are working. Right now they don't do anything so all you could do is assert that they are retaining the Dives that you are putting in them. Example:
#Test
public void testThatDivesRetainInformation(){
Athlete art = new Athlete("Art", "Canada");
Dive art1 = new Dive(art, 8.5);
Dive art2 = new Dive(art, 8.0);
Dive art3 = new Dive(art, 8.8);
Dive art4 = new Dive(art, 9.2);
assertThat(art.getDives().size(), is(5));
}
Then you could go through and add tests for things like, making sure that you can't construct a dive without an athlete, etc.
You could move construction of the athletes into the setup method of the test so you could use it all over the place. Most IDEs have support for doing that with a refactoring.