I am trying to simulate a library of Albums. But I would also be able to organise the contents of the library alphabetically by the author's name. Any help in how to organise the contents of the array of objects alphabetically?
I have created a Class called Album, which I use to create my objects
public class Album {
private String author;
private String name;
private String year;
public Album(String a, String n, String y) { // constructor
author = a;
name = n;
year = y;
}
public String toString()
{
return author +","+ name + "," + year;
}
}
The class Collection is used to store the objects into an array
public class AlbumCollection {
public Album collection[]= new Album[10];
private int numAlbums = 0;
public void add (Album a){
if (numAlbums >= collection.length){
Album newcollection[]= new Album [collection.length * 2];
for (int n = 0; n < numAlbums; n ++){
newcollection[n] = collection[n];
}
newcollection = collection;
}
collection[numAlbums] = a;
numAlbums = numAlbums + 1;
}
public String toString()
{
String details = "";
for ( int p = 0; p < collection.length ; p ++)
{
details = details + collection[p] + "\n" ;
}
details += "\n";
return details;
}
}
This is the class that I am using to create the Album Objects
public class TestCollection {
public static void main(String[] args) {
AlbumCollection c = new AlbumCollection();
c.add( new Album("DaftPunk","Discovery","2001"));
c.add( new Album ("Pink Floid","The Dark Side Of The Moon","1973"));
c.add( new Album( "The Clash", "London Calling", "1979"));
System.out.print(c);
}
}
I had to change the compareTo method to sort by the author.
public class Album {
private String author;
private String name;
private String year;
public Album(String a, String n, String y) { // constructor
author = a;
name = n;
year = y;
}
public String toString()
{
return author +","+ name + "," + year;
}
public int compareTo(Album a) {
// usually toString should not be used,
// instead one of the attributes or more in a comparator chain
return author.compareTo(a.author);
}
}
And i added method sort to sorting elements of array:
public class Collection {
public Album collection[]= new Album[10];
private int numAlbums = 0;
public void Add (Album a){
if (numAlbums >= collection.length){
Album newcollection[]= new Album [collection.length * 2];
for (int n = 0; n < numAlbums; n ++){
newcollection[n] = collection[n];
}
newcollection = collection;
}
collection[numAlbums] = a;
numAlbums = numAlbums + 1;
}
public String toString()
{
String details = "";
for ( int p = 0; p < numAlbums ; p ++)
{
details = details + collection[p] + "\n" ;
}
details += "\n";
return details;
}
public void sort(){
for(int i=0;i<numAlbums;i++){
for(int j=i;j<numAlbums-1;j++){
if(collection[j].compareTo(collection[j+1])>0){
Album tmp =collection[j];
collection[j]=collection[j+1];
collection[j+1]=tmp;
}
}
}
}
}
You can not use the length of an array, if you store the number of authors, because you will print null values
public static void main(String[] args) {
Collection c = new Collection();
c.Add( new Album("DaftPunk","Discovery","2001"));
c.Add( new Album ("Pink Floid","The Dark Side Of The Moon","1973"));
c.Add( new Album( "The Clash", "London Calling", "1979"));
c.sort();
System.out.print(c);
}
Related
I have created a program that sorts trading cards and places them in a collection that is then compared to other collections to look for duplicates. I have had no problems up until my final toString method. My issue is that I cannot seem to get the return statement to separate the various cards onto their own separate lines.
instead of Alan Turing, Grace Hopper, Ada Lovelace, I need:
Alan Turing
Grace Hopper
Ada Lovelace
Below is a copy of my code. I am fairly new to java so I apologize for any lack of knowledge pertaining to methods specific to this, but I have only found ones using System.out.println, and not mentioning return in any way. My problem lies in the method defined by **. I appreciate any and all help and am sorry if this question is not 100% clear. (I have tried my own research to no avail!)
// First Class
public class Card implements Comparable<Card> {
private String name;
private String nationality;
private int yearBorn;
private int yearDied;
public Card(String name, String nationality, int yearBorn, int yearDied) {
this.name=name;
this.nationality=nationality;
this.yearBorn=yearBorn;
this.yearDied=yearDied;
}
public int compareTo(Card c) {
if (this.name.equals(c.name)) return 0;
else if (this.name.compareTo(c.name)>0) return 1;
else return -1;
}
public String toString() {
return String.format("%s (%d - %d) - %s", name, yearBorn, yearDied, nationality);
}
}
// Second Class
import java.util.ArrayList;
import java.util.List;
public class CardCollection {
private String owner;
private List<Card> myCollection;
public CardCollection(String owner) {
this.owner = owner;
this.myCollection = new ArrayList<>();
}
public boolean addCard(Card c) {
int p = 0;
while (p < myCollection.size()) {
int q = myCollection.get(p).compareTo(c);
if (q == 0) {
return false;
} else if (q > 0) {
myCollection.add(p, c);
return true;
}
p++;
}
myCollection.add(c);
return true;
}
public void removeCard(int r) {
myCollection.remove(r);
}
public int getSize() {
return myCollection.size();
}
public ArrayList<Card> mergeCollections(CardCollection cc) {
ArrayList<Card> dupes = new ArrayList<>();
while (cc.getSize() > 0) {
Card c = cc.myCollection.remove(0);
if (myCollection.contains(c)) {
dupes.add(c);
}
else myCollection.add(c);
}
return dupes;
}
**public String toString() {
String s = "";
for (int i = 0; i < owner.length(); i++) {
s += "-";
}
return String.format("%s\n%s\n%s\n", owner, s, myCollection);**
}
}
// Runner Class
import java.util.ArrayList;
public class CCRunner {
public static void main(String[] args) {
CardCollection c1 = new CardCollection("Alan");
CardCollection c2 = new CardCollection("Grace");
Card turing = new Card("Alan Turing","British",1912,1954);
Card hopper = new Card("Grace Hopper","American",1906,1992);
Card vonneumann = new Card("John Von Neumann","Hungarian",1903,1957);
Card shannon = new Card("Claude Shannon","American",1916,2001);
Card johnson = new Card("Katherine Johnson","American",1918,-1);
Card lovelace = new Card("Ada Lovelace","British",1815,1852);
Card cerf = new Card("Vint Cerf","American",1943,-1);
Card brin = new Card("Sergey Brin","Russian",1973,-1);
c1.addCard(turing);
c1.addCard(vonneumann);
c1.addCard(shannon);
c1.addCard(johnson);
c1.addCard(cerf);
c1.addCard(brin);
c2.addCard(cerf);
c2.addCard(lovelace);
c2.addCard(johnson);
c2.addCard(vonneumann);
c2.addCard(hopper);
System.out.println(c1);
System.out.println(c2);
ArrayList<Card> dupes = c1.mergeCollections(c2);
System.out.println(c1);
System.out.println(c2);
System.out.println("Duplicates:\n-----------");
for (Card c : dupes) {
System.out.println(c);
}
}
}
This is run in a separate class, but I don't think it will elucidate my problem to include it. Let me know if I am wrong.
You can either change your implementation of toString() of your CardCollection class. Examples:
Loop again, this time over the List:
public final String toString() {
String s = "";
for (int i = 0; i < owner.length(); i++) {
s += "-";
}
for (int i = 0; i < myCollection.size(); i++) {
s += "\n" + myCollection.get(i);
}
return String.format("%s\n%s\n", owner, s);
}
Using a stream (requires an additional import java.util.stream.Collectors;):
public final String toString() {
String s = "";
for (int i = 0; i < owner.length(); i++) {
s += "-";
}
return String.format("%s\n%s\n%s\n",
owner,
s,
myCollection.stream()
.map(Card::toString)
.collect(Collectors.joining("\n")));
}
Or you can #Override the toString() method of the ArrayList, also in your CardCollection class. Example:
this.myCollection = new ArrayList<>(){
#Override
public String toString(){
String s = "";
if (size() > 0) s = get(0).toString();
for (int i = 1; i < size(); i++) {
s += "\n" + get(i).toString();
}
return s;
}
};
All examples will result in this for Alan (before the merge):
Alan
----
Alan Turing (1912 - 1954) - British
Claude Shannon (1916 - 2001) - American
John Von Neumann (1903 - 1957) - Hungarian
Katherine Johnson (1918 - -1) - American
Sergey Brin (1973 - -1) - Russian
Vint Cerf (1943 - -1) - American
Note: I'd personally go with changing the implementation of toString() of the CardCollection class. I would also perfer the way tquadrat did it in their answer. The overriding of ArrayList looks to messy in my opinion, and keeping the stringrepresentation in the toString() method makes more sense to me.
Try this as a replacement to the marked toString() implementation:
…
public final String toString()
{
var s = "-".repeat( owner.length() );
var joiner = new StringJoiner( "\n", String.format( "%s%n%s%n", owner, s ), "" );
for( var c : myCollection ) joiner.add( c.toString() );
var retValue = joiner.toString();
return retValue;
}
Basically, the output would look like this:
<owner>
-------
<collectible1>
<collectible2>
<…>
If you are using a Java version before Java 11, you may need to replace var with the respective types.
I want to create an object named "Course", and get the information from the keyboard. The last attribute called the "pre", which means the prerequisite courses of this course. I want to input the whole information in one line and extract the information for each attribute. But I got the problem with"pre". I run the program and the output of course.pre is null. I do not know why. Here is my Course class code:
`import java.util.HashSet;
public class Course{
private String name;
private int isFall;
private int NumPre;
private HashSet<Course> pre;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String setName (String n){
return name = n;
}
// 1 - fall 0 - both -1 - spring
public void setType(String isFall) {
if(isFall.equals("F") || isFall.equals("f")){
this.isFall = 1;
}else if(isFall.equals("S") || isFall.equals("s")){
this.isFall = -1;
}else if(isFall.equals("B") || isFall.equals("b")){
this.isFall = 0;
}
}
public int getType(){
return isFall;
}
public void SetNumPre(int n) {
this.NumPre = n;
}
public int getNumPre() {
return NumPre;
}
public void addPre(Course c) {
pre.add(c);
}
public HashSet<Course> getPre() {
return pre;
}
}
`
And here is my main method here:
import java.util.*;
public class TimeToGraduate {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
//System.out.print("Input first two integers here: ");
String globalInfo = scanner.nextLine();
String[] numOfCourse = globalInfo.split(" ");//[0] num of total course [1] max num per semester
int totalNum = Integer.parseInt(numOfCourse[0]);
int maxPre = Integer.parseInt(numOfCourse[1]);
Course courses[] = new Course[totalNum];
//System.out.print("Please input course list here: ");
String coursesList = scanner.nextLine();
String[] nameOfCourse = coursesList.split(" ");
for(int i = 0;i < totalNum; i++){
courses[i] = new Course(nameOfCourse[i]);
}
//System.out.print("Please input course info here: ");
for(int i = 0;i < totalNum; i++){
String courseInfo = scanner.nextLine();
String[] infoOfCourse = courseInfo.split(" ");
courses[i].setName(infoOfCourse[0]);
courses[i].setType(infoOfCourse[1]);
courses[i].SetNumPre(Integer.parseInt(infoOfCourse[2]));
if(courses[i].getNumPre() > 0){
for(int j = 3; j < 3+(courses[i].getNumPre()); j++){
for(int k = 0; k < totalNum; k++){
if(infoOfCourse[j] == courses[k].getName()){
courses[i].addPre(courses[k]);
}
}
}
}
}
scanner.close();
for(int m = 0; m < totalNum; m++){
System.out.print(courses[m].getName()+" ");
System.out.print(courses[m].getType()+" ");
System.out.print(courses[m].getNumPre()+" ");
System.out.print(courses[m].getPre()+" ");
System.out.println();
}
}
}
Notice that you did not initilize the pre attribute. That is why it is null.
It would be a good practise if you initilize the pre inside a constructor for the Course class. Otherwise, do it when you start filling the Course attributes.
Update:
Your constructor should be like this:
public Course() { this.pre = new HashSet()}
As you can see the constructor does not have any arguements, because you will be filling its attribute from the main function.
You can define a constructor with arguments too:
public Course(String name, HashSet<Course> pre)
{ this.name = name; this.pre = pre; }
But you will need to initilize pre and name when you call it from the main:
...
HashSet hs = new HashSet();
course[i] = new Course('course_name', hs);
....
public class Main {
public static void main(String[] args) throws FileNotFoundException {
ArrayList<Country> cList = new ArrayList<Country>();
ArrayList choice = new ArrayList();
File inf = new File("src/countrydata.txt");
Scanner scan = new Scanner(inf).useDelimiter("[\t|\n|\r]+");
Scanner s = new Scanner(System.in);
int p = 0;
double g = 0;
while(scan.hasNext()){
cList.add(new Country(scan.next(), scan.nextInt(), scan.nextDouble()));
}
System.out.print("Would you like in sorted my name(n), population(p) or growth(g): ");
String go = s.next();
go = go.toLowerCase();
if(go.equals("n")){
choice.add(go);
}else if(go.equals("p")){
choice.add(p);
}else if(go.equals("g")){
choice.add(g);
}
MyUtil.bubbleSort(cList, choice);
My Error: (Line above) Bound mismatch: The generic method bubbleSort(List, List) of type MyUtil is not applicable for the arguments (ArrayList, ArrayList). The inferred type Country is not a valid substitute for the bounded parameter >
}
//Sort Class
public class MyUtil <E extends Comparable<E>>{
public static <E extends Comparable<E>>void bubbleSort(List<E> list, List choice){
int n = list.size();
boolean swap = true;
while(swap){
swap = false;
for(int i = 0; i < n-1; i++){
if(list.get(i).compareTo(list.get(i+1)) == 1){
swap(list, i, i+1);
swap = true;
}
}
}
}
public static <E extends Comparable<E>>void swap(List<E> list, int i, int j){
E temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
public class Country {
private String name;
private int population;
private double growth;
public Country(String name, int population, double growth){
this.name = name;
this.population = population;
this.growth = growth;
}
public String getName(){return name;}
public int getPopulation(){return population;}
public double getGrowth(){return growth;}
public String toString(){
return name + ", population of " + population + ", with an anual growth of: " + growth + ".";
}
public int compareTo(Country c, String s){
if(name.substring(0, 1).compareTo(c.getName().substring(0, 1)) > 0){
return -1;
}else if(name.substring(0, 1).compareTo(c.getName().substring(0, 1)) == 0){
return 0;
}else{
return 1;
}
}
public int compareTo(Country c, int p){
if(population < c.getPopulation()){
return -1;
}else if(population == c.getPopulation()){
return 0;
}else{
return 1;
}
}
public int compareTo(Country c, double g){
if(growth < c.getGrowth()){
return -1;
}else if(growth == c.getGrowth()){
return 0;
}else{
return 1;
}
}
}
The issue is that you've specified in the line
public static <E extends Comparable<E>>void bubbleSort(List<E> list, List choice)
that E must extend Comparable<E> and Country does not. In order to make it compile, you'd have to change
public class Country {
to
public class Country implements Comparable<Country> {
and you'll also have to implement
public int compareTo(Country c) {}
but doing it that way won't give you the flexibility to sort by multiple different dimensions.
I want to list dates from the most current date to the oldest date.
I don't want to use Collections.sort()so I made my own method.
When I do this :
List<Livre> maBibliotheque = new ArrayList<Livre>();
boolean tri = false;
int born = maBibliotheque.size();
while (tri == false)
{
tri = true ;
for (int i=0; i<born-1;i++)
{
if ( maBibliotheque.get(i).getNewPeriode().compareTo(maBibliotheque.get(i+1).getNewPeriode())>0){
Livre livre = maBibliotheque.get(i);
maBibliotheque.set(i, maBibliotheque.get(i+1));
maBibliotheque.set(i+1,livre);
tri = false ; }
}
born -= born;
}
It works perfectly, but from the oldest to the newest date, but I want the otherwise.
I change this line to
if ( maBibliotheque.get(i).getNewPeriode().compareTo(maBibliotheque.get(i+1).getNewPeriode())<0){
But it's doesn't make anything, no sort dates in this case. Please help
To reverse the order, replace > 0 with < 0
Doesn't
born -= born;
do the same as
born = 0;
I suspect this isn't needed.
This
public static void main(String[] args) throws IOException, IllegalAccessException, NoSuchFieldException {
List<Livre> maBibliotheque = new ArrayList<Livre>();
maBibliotheque.add(new Livre("aaa"));
maBibliotheque.add(new Livre("abb"));
maBibliotheque.add(new Livre("bbb"));
maBibliotheque.add(new Livre("000"));
boolean tri;
int born = maBibliotheque.size();
do {
tri = true;
for (int i = 0; i < born - 1; i++) {
if (maBibliotheque.get(i).getNewPeriode().compareTo(maBibliotheque.get(i + 1).getNewPeriode()) > 0) {
Livre livre = maBibliotheque.get(i);
maBibliotheque.set(i, maBibliotheque.get(i + 1));
maBibliotheque.set(i + 1, livre);
tri = false;
}
}
} while (!tri);
System.out.println("increasing: " + maBibliotheque);
do {
tri = true;
for (int i = 0; i < born - 1; i++) {
if (maBibliotheque.get(i).getNewPeriode().compareTo(maBibliotheque.get(i + 1).getNewPeriode()) < 0) {
Livre livre = maBibliotheque.get(i);
maBibliotheque.set(i, maBibliotheque.get(i + 1));
maBibliotheque.set(i + 1, livre);
tri = false;
}
}
} while (!tri);
System.out.println("decreasing: " + maBibliotheque);
}
static class Livre {
private final String newPeriode;
Livre(String newPeriode) {
this.newPeriode = newPeriode;
}
public String getNewPeriode() {
return newPeriode;
}
#Override
public String toString() {
return "Livre{" +
"newPeriode='" + newPeriode + '\'' +
'}';
}
}
prints
increasing: [Livre{newPeriode='000'}, Livre{newPeriode='aaa'}, Livre{newPeriode='abb'}, Livre{newPeriode='bbb'}]
decreasing: [Livre{newPeriode='bbb'}, Livre{newPeriode='abb'}, Livre{newPeriode='aaa'}, Livre{newPeriode='000'}]
Sort from oldest to newest, then reverse it with Collections.reverse(maBibliotheque);
I would recommend implementing a Comparator. You set a field in the Comparator object that can tell it whether to sort Ascending or Descending, then call Collections.sort(maBibliotheque, new MyComparator(MyComparator.DESC))
Demo (adjust generics as needed, and if, as in this case, you know that you're comparing with a specific field use o1.getField().compareTo(o2.getField()). Alternately, you could implement Comparable in your Object and just call Collections.sort(List), but that's not as flexible.
public class MyComparator implements Comparator<String>
{
public static final int ASC = 0;
public static final int DESC = 1;
private final int sortOrder;
public MyComparator(int sortOrder)
{
this.sortOrder = sortOrder;
}
/* (non-Javadoc)
* #see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
#Override
public int compare(String o1, String o2)
{
switch(this.sortOrder)
{
case ASC:
return o1.compareTo(o2);
case DESC:
return o2.compareTo(o1);
}
return 0;
}
}
I have used this site to help me on many of my programming assignments before but I can not find anything similar to the issue that I am having now.
I am trying to first print the myHobbies array in the toString of the person class using the method printHobby, as well as calculate the total duration the the user has been doing the Hobby in printDuration. I am not sure why I can not get it to work and have been struggling with it for a while.
Any help would be appreciated. Here are my classes. This is my first time posting so if I am doing something wrong, please let me know.
//--------------------Person--------------------
public class Person {
String fName;
String lName;
String address;
int age;
String hobbyText;
private double durationH = 0;
private double totalDuration = 0;
Person(String f, String l, String a, int ag) {
fName = f;
lName = l;
address = a;
age = ag;
}
static Hobby[] myHobbies = new Hobby[5];
static int i = 0;
public static void setHobby(Hobby mh) {
myHobbies[i] = mh;
i++;
}
public String toString() {
return fName + " " + lName + " " + address + " " + age + " "
+ printDuration() + " ";
}
public double printDuration() {
for (int k = 0; k < myHobbies.length; k++)
totalDuration += myHobbies[k].getDuration();
return totalDuration;
}
public String printHobbies() {
for (int j = 0; j < myHobbies.length; j++)
hobbyText = myHobbies[j].toString();
return hobbyText;
}
}
//--------------------HobbyDriver--------------------
import java.util.Scanner;
public class HobbyDriver {
public static void main(String[] args) {
Hobby[] newHobby = {
new Hobby("Comics", "09/25/2012", "The Comic Store", 1),
new Hobby("Baseball", "09/30/2012", "Fenway Park", 3),
new Hobby("Programming", "09/212/2012", "Home", 6),
new Hobby("Board Games", "09/01/2012", "Tom's House", 3),
new Hobby("Watching Dr. Who", "09/27/2012", "Home", 1) };
String personChoice;
Scanner hobbyScan = new Scanner(System.in);
do {
String fName;
String lName;
int age;
String address;
String hobbyName;
String partDate;
String location;
double duration;
int userHobby;
String hobbyChoice;
System.out.println("What is your first name?");
fName = hobbyScan.nextLine();
System.out.println("What is your last name?");
lName = hobbyScan.nextLine();
System.out.println("What is your address?");
address = hobbyScan.nextLine();
System.out.println("What is your age?");
age = hobbyScan.nextInt();
hobbyScan.nextLine();
do {
System.out
.println("What hobbies would you like to do?\n"
+ "choose between Comics(0)\nBaseball(1)\nProgramming(2)\nBoard Games(3)\nWatching Dr.Who(4)\n"
+ "\nEnter the name of the hobby and then press enter");
userHobby = hobbyScan.nextInt();
hobbyScan.nextLine();
System.out
.println("Would you like to add another hobby? (enter yes/no)");
hobbyChoice = hobbyScan.nextLine();
Person.setHobby(newHobby[userHobby]);
} while (hobbyChoice.equals("yes"));
System.out
.println("Would you like to add another person? (enter yes/no)");
personChoice = hobbyScan.nextLine();
int i = 0;
Person[] newPerson = new Person[5];
newPerson[i] = new Person(fName, lName, address, age);
System.out.println(newPerson[i].toString());
i++;
} while (personChoice.equals("yes"));
}
}
//--------------------Hobby--------------------
public class Hobby {
private String hobbyName;
private String partDate;
private String location;
private double duration;
Hobby(String h, String p, String l, double d) {
hobbyName = h;
partDate = p;
location = l;
duration = d;
}
public String toString() {
return hobbyName + " " + partDate + " " + location + " " + duration;
}
public void setDuration(double d) {
d = duration;
}
public double getDuration() {
return duration;
}
}
the problem is the following:
public String printHobbies() {
for (int j = 0; j < myHobbies.length; j++)
hobbyText = myHobbies[j].toString();
return hobbyText;
}
First, you overwrite your string in each loop. Write
hobbyText += myHobbies[j].toString();
Second, You will get a NPE if you don't add 5 Hobbies, because every item in the array is null at the beginning.
So you will have to check if myHobbies[j] is not null:
public String printHobbies() {
for (int j = 0; j < myHobbies.length; j++) {
if(myHobbies[j] != null) {
hobbyText += myHobbies[j].toString();
}
}
return hobbyText;
}
You also may want to have a look at Collections: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html
There are few bugs which may cause an issue in your code, it depends on current usage.
You do not reset the total duration, which means, that it returns proper result only after the first invocation. Otherwise it is multiplied by the number of invocations.
public double printDuration() {
for (int k = 0; k < myHobbies.length; k++)
totalDuration += myHobbies[k].getDuration();
return totalDuration;
}
You use the simple array with the fix size 5. It means, that if you add more than 5 hobbies, it will throw IndexOutOfBoundsException.
You call toString() method on all hobbies in the array nevertheless they were set. The arrays are initialized to null by default, which means, that if you set less than 5 hobbies, you try to call it on null which throws NullPointerException.
public String printHobbies() {
for (int j = 0; j < myHobbies.length; j++)
hobbyText += myHobbies[j].toString();
return hobbyText;
}