check if an object exist, using field string - java

I have a Song class(field: String name) and an Album class (initialize an Arraylist fill with Song objects), I am adding a method (addSongAlbum(String name parameter))that first check if the song is already in the album. Everything works fine but now I want to check too if the song exist outside the album. How can I do this taking in consideration that the input of the method is a String?
public void addSongToAlbum(String name){
if(checkExist(name) == null){
album.add(checkExist(name));
System.out.println("Song "+name+" was successfully added");
} else {
System.out.println("This song is already in the album");
}
}
private Song checkExist(String name){
for(int i=0; i<album.size(); i++){
if(name.equals(album.get(i).getName())){
return album.get(i);
}
}
return null;
}

I'd create a central Songmanager object that is available to all objects working with Songs, like so
public class SongManager {
private static SongManager sMan;
private Map<String, Song> songs = new HashMap<String, Song>();
public static SongManager getInstance() {
if (sMan == null) {
sMan = new SongManager();
}
return sMan;
}
public void addSong(Song s) {
songs.put(s.getName, s);
}
public Song getSong(String name) {
return songs.get(name);
}
}
your songs can be simple container classes, like so
public class Song {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
You can access this manager everywhere by calling SongManager.getInstance(). Create a simple container class for songs all existing Songs to this Manager and in youraddSongMethod, simply call thegetSong` method to see if the song exists.
P.s. I know that the Singleton pattern I'm using here is very controversal (see e.g. What is so bad about singletons?, but to me it is the easiest working alternative here.

You would need to have a List of all the Song objects somewhere. Either add them to a static List when constructing (you would need to remember to remove them when no longer used to let the memory be garbage collected), or have a similar List of all Album objects and then search through those. The first one is useful if you want to check all Song objects that were created, the second one if you only want to check those that are in albums.

Related

How to save user choice into new array list

I’m sure I wasn’t clear enough in the title, clarifying everything here. I have a passenger booking a flight, I want to make a list in which the flights booked by the passenger will be stored.
This is the part of the code where the passenger completes the reservation, how do I make a new list and add a booked flight in it
#Override
public void payingFirstClassWithoutPromoCode(ArrayList<Flight> flightsList) {
System.out.println("Confirm buying ticket: (yes or no)");
String confirmation = scanner.nextLine();
if (confirmation.equalsIgnoreCase("yes")) {
if (selectedPassenger.getBalance() >= selectedFlight.getPriceForFirstClass()) {
System.out.println("Successful reserved!");
selectedPassenger.setBalance(selectedPassenger.getBalance() - selectedFlight.getPriceForFirstClass());
System.out.println(selectedPassenger.getFirstName() + "'s new balance is: " + selectedPassenger.getBalance());
} else {
noFundsAvailable(flightsList);
}
} else if (confirmation.equalsIgnoreCase("no")) {
cancellation(flightsList);
} else {
System.out.println("Wrong input!");
}
}
I think you can add a Flight field in your Passenger class, then do
selectedPassenger.setFlight(selectedFlight)
Here's the passenger class
class Passenger{
//other fields
Flight flight;
public void setFlight(Flight f){
this.flight = f;
}
If a passenger can have multiple flight, then declare a List in your passenger class, then do
selectedPassenger.getFlights().add(selectedFlight);
class Passenger{
//other fields
List<Flight> flight;
public Passenger(){
//don't forget to initialize flight list
flight = new ArrayList();
}
public List<Flight> getFlights(){
return this.flight ;
}
instead of fetching the whole list and adding it manually, you can have a method in your passenger class like
public void addFlight(Flight f){
this.flight.add(f);
}
then you can do
selectedPassenger.addFlight(selectedFlight);
You could design your Passenger class like this:
public class Passenger {
private String name;
private List<Flight> flights;
//Getter and setter for name
public Passenger(String name) {
this.name = name;
this.flights = new ArrayList<>();
}
public void addFlight(Flight flight) {
flights.add(flight);
}
}
On a side note, it might be worth refactoring your code. I note that you named your method payingFirstClassWithoutPromoCode(ArrayList<Flight> flightsList). I imagine you will have many more options, which means you will have to write multiple methods with very similar code.
It can be a good idea to make one method that can handle many different scenarios.
For example, you can add the ticket type (first/business/economy class) as an parameter in your method: payingWithoutPromoCode(ArrayList<Flight> flightsList, String ticketType).
It means you have to rewrite your method a little bit. In my example, you probably need to rewrite the methods in your Flight class. Instead of selectedFlight.getPriceForFirstClass() you can do selectedFlight.getPrice(ticketType).

Object + List of Objects in a List?

I've got an interesting and troublesome task to solve.
I need to create a playlist (some kind of list) that contains songs and other sub-playlists of songs... Each playlist has a playing mode (random, sequence, etc.) Is it possible to create such playlist?
I thought about cracking the sub-playlists and adding extraxted songs from it to the master playlist or creating a sub-playlist for every song that is added to master playlist (I don't really like this idea)
Somehow it gets around the problem however it is necessary to remain playing mode of each playlist...
For example:
Master playlist(sequence palymode) has:
(1) song1-1/
(2) subplaylist(song2-1, song2-2, song-2-3) with random playmode/
(3) song1-2
The desired outcome:
(1) song1-1/
(2) song2-3 (starting random subplaylist)/
(3) song2-1/
(4) song2-2/
(5) song1-2/
how should I approach this?
Since I suspect that this is some sort of homework, I will only provide you with a partial implementation, so you get an idea how to proceed.
Create an abstract class PlaylistElement, which can later either be a Song or another Playlist.
abstract class PlaylistElement {
public abstract List<Song> printSongs();
}
Implement a class Playlist extending PlaylistElement.
class Playlist extends PlaylistElement {
private List<PlaylistElement> elements;
private PlaybackMode playbackMode;
#Override
public List<Song> printSongs() {
if(this.playbackMode == PlaybackMode.RANDOM) {
List<Song> songs = new ArrayList<>();
List<PlaylistElement> shuffleElements = new ArrayList<>();
//Add all PlaylistElements from elements into shuffleElements
//and shuffle the shuffleElements collection
//insert your songs into the songs collection here by sequentially
//going through your
//PlaylistElements and inserting the result of their printSongs()
//implementation (e.g. in a for-loop)
return songs;
}
else if(this.playbackMode == PlaybackMode.SEQUENTIAL) {
//you can do this on your own
}
return null;
}
}
Implement a class Song extending PlaylistElement.
class Song extends PlaylistElement {
private String title;
private String artist;
.
.
.
#Override
public List<Song> printSongs() {
//return a List with only this Song instance inside
return Arrays.asList(new Song[] { this });
}
}
Create an enum for your Playlist Playback Modes.
enum PlaybackMode {
SEQUENTIAL, RANDOM;
}
Hope this gives you a general idea! Getters/Setters and other important parts omitted for brevity.
Altough there are already some answers, i promised to provide a sample implementation. Starting of we have a common interface Playable which is the class to be implemented for the composite design pattern.
public interface Playable {
String getSongName();
}
Next, the Song class to represent a single song.
public class Song implements Playable {
private String name;
public Song(String name) {
this.name = name;
}
#Override
public String getSongName() {
return name;
}
}
In preparation for the Playlist class an enum to represent the difference playing modes.
public enum PlayingMode {
SEQUENCE, RANDOM
}
Now, finally the playlist class.
public class Playlist implements Playable {
private String name;
private List<Playable> playables = new ArrayList<>();
private PlayingMode mode;
private Playable currentItem;
private List<Playable> next = new ArrayList<>();
public Playlist(String name, PlayingMode mode) {
this.name = name;
this.mode = mode;
}
#Override
public String getSongName() {
if (playables.isEmpty()) {
return null;
}
if (currentItem == null) {
// initialize the playing songs
next.addAll(playables);
if (mode == PlayingMode.RANDOM) {
Collections.shuffle(next);
}
currentItem = next.get(0);
} else {
// if we have a playlist, play its songs first
if (currentItem instanceof Playlist) {
String candidate = currentItem.getSongName();
if (candidate != null) {
return candidate;
}
}
int index = next.indexOf(currentItem);
index++;
if (index < next.size()) {
currentItem = next.get(index);
} else {
currentItem = null;
}
}
return currentItem != null ? currentItem.getSongName() : null;
}
private void addToNext(Playable playable) {
if (currentItem == null) {
return;
}
// if the playlist is playing, add it to those list as well
if (mode == PlayingMode.SEQUENCE) {
next.add(playable);
} else if (mode == PlayingMode.RANDOM) {
int currentIndex = next.indexOf(currentItem);
int random = ThreadLocalRandom.current().nextInt(currentIndex, next.size());
next.add(random, playable);
}
}
public void addPlayable(Playable playable) {
Objects.requireNonNull(playable);
playables.add(playable);
addToNext(playable);
}
}
Some examples:
public static void main(String[] args) {
Song song1 = new Song("Song 1");
Song song2 = new Song("Song 2");
Playlist subPlaylist1 = new Playlist("Playlist 1", PlayingMode.RANDOM);
subPlaylist1.addPlayable(new Song("Song A"));
subPlaylist1.addPlayable(new Song("Song B"));
subPlaylist1.addPlayable(new Song("Song C"));
Song song3 = new Song("Song 3");
Playlist main = new Playlist("Main", PlayingMode.SEQUENCE);
main.addPlayable(song1);
main.addPlayable(song2);
main.addPlayable(subPlaylist1);
main.addPlayable(song3);
String songName = main.getSongName();
while (songName != null) {
System.out.println("Current song is: " + songName);
songName = main.getSongName();
}
}
Could give the output:
Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song C
Current song is: Song 3
You can also add songs while playing:
while (songName != null) {
System.out.println("Current song is: " + songName);
songName = main.getSongName();
// add songs while playing
if ("Song A".equals(songName)) {
subPlaylist1.addPlayable(new Song("Song D"));
subPlaylist1.addPlayable(new Song("Song E"));
subPlaylist1.addPlayable(new Song("Song F"));
}
}
This could lead to:
Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song E
Current song is: Song D
Current song is: Song F
Current song is: Song C
Current song is: Song 3
Some final notes:
The getIndex method does have a worst case runtime of O(n), which can be an issue if there are many songs in the playlist. A faster Collection like Set or Map will give better performace, but the implementation is a bit more complex.
The classes have been simplified, which means some getters and setters as well as equals and hashCode have been omitted for brevity.
Approach 1:
Create a class named playlist and playlist item which can hold list of songIds, which can hold set of songs from different playlists or song ids.
class PlayList{
List<PlayListItem> playlistItems;
}
class PlayListItem{
List<String> songIds;
}
This helps if a particular if you want to identify the set of songs added via a particular sub playlist. However this approach makes the iteration little difficult compared to approach 2
Approach 2:
Here the list is avoided in playlist item, so that iteration while displaying playlist is simple. However to identify the list of songIds that was added via a particularSubPlaylist has to be computed.
class PlayList{
List<PlayListItem> playlistItems;
}
class PlayListItem{
String songId;
String referencePlayListId;
}

phonebook with arraylist in java

I want to try a simple implementation of phonebook with arraylist in java.
First I made a class contains what the info. needed and second I want have another class which have methods like getting info and printing them.
and because I want to use array list this is what I've done so far, but the 'print' method keep giving me the error in for loop, is there any one who can help me to optimize my code and why I have this error.
this is the first class :
public class PhoneBook {
long number;
String name;
.
.
.
.
getter() and setter();
}
The second class with methods:
public class PhoneBookMethods {
ArrayList<PhoneBook> phoneBooks = new ArrayList<PhoneBook>();
public void getInfo(PhoneBook phoneBooks)
{
.
.
.
}
public void print(PhoneBook phoneBooks)
{
for (PhoneBook p: phoneBooks) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
}
In your for-each loop, change
for (PhoneBook p: phoneBooks)
to
for (PhoneBook p: this.phoneBooks)
so that you would be accessing the phoneBooks arraylist, not the argument of the print method.
EDIT:
You can use the "this" keyword to make your code much more "explicit".
For the example, in your case you have an argument called phoneBooks that has the same name as your ArrayList (member variable). So to explicitly differentiate between the two of them, use this.phonebooks to access the member variable phoneBooks(the ArrayList), and use phoneBooks to refer to the argument.
If you want to use instance variable phoneBooks then no need to pass any param in the method print().
public void print()
{
for (PhoneBook p: phoneBooks) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
OR if you really want to pass param rename the param name
public void print(ArrayList<PhoneBook> phoneBookList)
{
for (PhoneBook p: phoneBookList) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
public void print(PhoneBook phoneBooks)
Your parameter phoneBooks masks the field (the array) also named phoneBooks. So compiler tries to treat parameter as list and failes.
Actually at first you have some design issues. The way you think what is a PhoneBook is invalid. You should consider a phonebook something holds several phones on it. Therefore, you may have a phone class like below:
public class Phone {
private String number;
private String name;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And a phonebook class responsible for holding those phone objects:
public class PhoneBook extends ArrayList<Phone> {
#Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (Phone phone : this) {
stringBuilder.append("----------------------------\n");
stringBuilder.append("Name:" + phone.getName() + "\n");
stringBuilder.append("Number:" + phone.getNumber() + "\n");
}
return stringBuilder.toString();
}
}
It is a arraylist of Phone, nothing more. Thus, you can add or remove a phone directly via phone book. This is how to use it:
public class MAIN {
public static void main(String[] args) {
Phone myPhone = new Phone();
myPhone.setName("Eray");
myPhone.setNumber("0533XXXXXXX");
Phone girlfriendPhone = new Phone();
girlfriendPhone.setName("Canan");
girlfriendPhone.setNumber("0544XXXXXXX");
Phone yourPhone = new Phone();
yourPhone.setName("Bita Mirshafiee");
yourPhone.setNumber("0599XXXXXXX");
PhoneBook phoneBook = new PhoneBook();
phoneBook.add(myPhone);
phoneBook.add(girlfriendPhone);
phoneBook.add(yourPhone);
System.out.println(phoneBook);
}
}
Finally, this is the output:
----------------------------
Name:Eray
Number:0533XXXXXXX
----------------------------
Name:Canan
Number:0544XXXXXXX
----------------------------
Name:Bita Mirshafiee
Number:0599XXXXXXX

Best way to store collection of objects in Java?

I am creating a dump Java app for student information system for learning and implementing OOPS Concepts like inheritance, abstraction, polymorphism and encapsulation.
What I am doing is, I have created Faculty Class, Student Class and a College Class. Now i want to add new faculty in College. So my approach is to create a method in College class i.e. addFaculty(Faculty f) and fireFaculty(Faculty f), now i want to add Faculties in College class.
Whats the best way to do it? How do i store list of Faculty Object in College Object. Because i can add more than one faculty and more than one student in college.
Whats the best approach to solve this problem in OOPS?
Here is College.java code which i have implemented, it works fine but is this the best way i can solve it?
public class College
{
String name;
String location;
String courses[];
HashMap<String,Faculty> faculties;
int noOfFaculties = 0;
int noOfStudents = 0;
public College(String name,String location,String courses[])
{
this.name = name;
this.location = location;
this.courses = courses;
faculties = new HashMap<>();
}
public void addFaculty(Faculty faculty)
{
faculties.put(faculty.getName(),faculty);
}
public void printFaculties()
{
Set<String> set = faculties.keySet();
if(set.size()>0)
{
for(String s:set)
{
System.out.println(faculties.get(s).getName());
}
}
else
{
System.out.println("No Faculties Currently Working");
}
}
public void fireFaculty(Faculty faculty)
{
faculties.remove(faculty.getName());
}
public String getName()
{
return name;
}
public String getLocation()
{
return location;
}
public String[] getCourses()
{
return courses;
}
}
If you cannot have duplicates use HashSet<Faculty> if you dont mind use a List<Faculty>.
Example:
class College {
private List<Faculty> listFactories = new ArrayList<>(); // dupes allowed
private Set<Faculty> setFactories = new HashSet<>(); // no dupes allowed
}
Check collections API.
There's a ton of ways you can do it. Probably the easiest way to handle storing a collection of objects is by using one of the Collections provided by Java. For beginners, probably the easiest one to understand is an ArrayList, which is basically an array that grows in size dynamically depending on the amount of objects in the collection.
So, as an axample, your code might be something like this:
public class College
{
private ArrayList<Faculty> faculty;
public College()
{
faculty = new ArrayList<Faculty>();
}
public void addFaculty(Faculty f)
{
faculty.add(f);
}
public void fireFaculty(Faculty f)
{
faculty.remove(f);
}
}
imho It depends what kind of services College college offers. If I were coding, I would start with:-
List<Faculy> faculties = new ArrayList<>();
....
public void addFaculty(Faculty f) {
faculties.add(f);
}
//... etc
And change to an altearnative later if needed.

Casting and ArrayList

I have an ArrayList that contains a number of songs objects.
ArrayList<Song> aSong = new ArrayList<Song>();
The Song class looks like this:
public class Song {
private String sName;
private String sLength;
public Song(String name, String length){
sName = name;
sLength= length;
}
public String getName(){
return sName;
}
public String getLength(){
return sLength;
}
public void edit(String name, String length){
sName = name;
sLength= length;
}
}
I'm trying to see if a song exists with the ArrayList method "contains"
// example
aSong.contains("Song 1")
but this returns false even though the song does really exist in the ArrayList.
Any help would be highly appreciated and thank you in advance.
No, "Song 1" definitely doesn't exist in the ArrayList - because that's a string, not a Song.
Three options:
Check for each song in the list to see whether it has that name. This is reasonably easy to do, but if you need that functionality in multiple places you'd definitely want to extract it into a separate method. Something like:
public static Song findSongByName(Iterable<? extends Song> songList,
String name)
{
// TODO: Nullity checks
for (Song song : songList)
{
if (song.getName().equals(name))
{
return song;
}
}
return null;
}
Override equals in Song based on the name of the song, and then call aSong.contains(new Song("Song 1"). This probably isn't a good idea, as I suspect that if you've got two Song objects with the same name but different lengths, you don't want to consider them as equal.
Build a Map<String, Song> so that you can look up songs in the list based on their name. This would be a good idea if you needed to look up multiple songs from the same list.
"Song 1" is a string, it's not the same as any Song object. Sounds to me that you are still at the stage where you think the language can guess what you want, rather than realising you have to tell it exactly and precisely what you want.
You could write a for loop and go though your list one by one, looking for the right title. Or perhaps you should switch to using a HashMap<String, Song>, that would let you look up a song by it's title.
You can define a function find that searches for and returns the first object that satisfies the given predicate.
public static <A> A find(final Iterable<A> iterable, final Predicate<A> predicate) {
for(final A item : iterable) {
if(predicate.isSatisfiedBy(item)) {
return item;
}
}
return null;
}
where Predicate is:
interface Predicate<A> {
boolean isSatisfiedBy(final A a);
}
You could use this function for your purpose as shown below:
final Song song = find(songs,
new Predicate<Song>() {
boolean isSatisfiedBy(final Song s) {
return s.getName().equals("Song 1");
}
}
);

Categories