Im trying to iterate a Linked List inside of a linked list but I'm not sure how to proceed with it. I'm used to using a passed parameter for what will be iterated but when I'm iterating a linked list within a linked list I won't know the list that will have a match for the element that I'm comparing to.
currently, the iterator for the inner linkedlist "nestedLinkedListIterator" is preventing compile because "nestedAlbum" does not have a corresponding parameter. I didn't provide a parameter because the inner LinkedList "nestedLinkedListIterator" could potentially be changing as the outer Linked list is iterated through while being checked with the passed title parameter into the dummy object.
Here is an example of what I’m trying to do
private static boolean addSongFromAlbumToAlbum(LinkedList<Album> albums1, LinkedList<Song> targetAlbum,
String title){
//creating a dummy song for comparison using title parameter with arbitrary time duration.
Song dummySong = new Song(title, 000);
ListIterator<Album> albumsListIterator = albums1.listIterator();
ListIterator<Song> targetAlbumListIterator = targetAlbum.listIterator();
//nested LinkedList iterator (for the song LinkedList is each album being iterated.
ListIterator<Song> nestedLinkedListIterator = nestedAlbum.listIterator();
/*if the "nestedAlbum" is going to change with every iteration of the outer Linked list how can I
* use the nestedAlbum.listIterator with it. normaly I am used to using a parameter tha is passed in
* the place of "nestedAlbum" but I don't think that would work because wither every new album element in "albums1"
* there will be a new song list. correct me if im wrong*/
//checking whether the song with the "title" parameter entered exists in the LinkedList
//of albums
while(albumsListIterator.hasNext()){
while(nestedLinkedListIterator.hasNext()){
//checking if current iteration has an object with same value for title as title parameter.
Song comparisonSongToAdd = nestedLinkedListIterator.next();
int comparisonValue = comparisonSongToAdd.getTitle().compareTo(title);
if(comparisonValue ==0){
//check whether the found object already exists in the album
while (targetAlbumListIterator.hasNext()){
SongComparator comparator = new SongComparator(); //create new comparator object to compare
int comparatorValue = comparator.compare(comparisonSongToAdd, targetAlbumListIterator.next());
if (comparatorValue == 0) {
System.out.println(comparisonSongToAdd + " already exists in the Album. please choose\n a different song.");
return false;
}//end if comparator
}//end target album while
targetAlbumListIterator.add(comparisonSongToAdd);
}//end if song title found
}//end nested album while
}//end albums while iterator
return true;
}//end addSongFromAlbum method
///SongComparator class
import java.util.Comparator;
public class SongComparator implements Comparator<Song> {
public int compare(Song song1, Song song2){
if(song1.getTitle() == song2.getTitle() && song1.getDurationSeconds() == song2.getDurationSeconds()){
return 0;
}else{
return -1;
}
}
}
1 Answer 1
I did not fully understand what you were trying to achieve with your code, but I will try to answer your question starting from @markspace's observation.
So I will be assuming that you are trying to iterate through a list of albums: albums1
and save all the songs which match the given title
in the targetAlbum
variable.
There are multiple points that can be improved in your code:
- the variable
dummySong
is redundant - using iterators makes the code harder to read, try going for
for
loops - a comparator cannot be used to naturally order songs (2 songs with different titles cannot be compared), so it's best to go for using the equals() method
This is a method that should cover what you asked for in your post:
private static boolean addSongFromAlbumToAlbum(LinkedList<LinkedList<Song>> albums, LinkedList<Song> targetAlbum, String title) {
ListIterator<LinkedList<Song>> albumsListIterator = albums.listIterator();
ListIterator<Song> targetAlbumListIterator = targetAlbum.listIterator();
ListIterator<Song> albumSongListIterator;
while(albumsListIterator.hasNext()) {
LinkedList<Song> currentAlbumSongs = albumsListIterator.next();
albumSongListIterator = currentAlbumSongs.listIterator();
while(albumSongListIterator.hasNext()) {
Song comparisonSongToAdd = albumSongListIterator.next();
boolean songMatchFound = comparisonSongToAdd.getTitle().equals(title);
if(songMatchFound){
while (targetAlbumListIterator.hasNext()) {
Song currentTargetAlbumSong = targetAlbumListIterator.next();
if (currentTargetAlbumSong.equals(comparisonSongToAdd)) {
System.out.println(comparisonSongToAdd + " already exists in the Album. please choose\n a different song.");
return false;
}
}
targetAlbumListIterator.add(comparisonSongToAdd);
}
}
}
return true;
}
Below is a demo program that covers:
- a main function to test the program
- my interpretation of Album and Song
- an equals method on the Song class
- a refactored method covering my points above
public class HelloWorld {
public static void main(String []args) {
LinkedList<Song> greenDayAlbum = new LinkedList<>();
greenDayAlbum.add(new Song("21 Guns", 3));
greenDayAlbum.add(new Song("Basket Case", 3));
greenDayAlbum.add(new Song("American Idiot", 3));
LinkedList<Song> linkinParkAlbum = new LinkedList<>();
linkinParkAlbum.add(new Song("Numb", 3));
linkinParkAlbum.add(new Song("In the end", 3));
linkinParkAlbum.add(new Song("Castle of glass", 3));
LinkedList<LinkedList<Song>> albums = new LinkedList<>();
albums.add(greenDayAlbum);
albums.add(linkinParkAlbum);
LinkedList<Song> targetAlbum = new LinkedList<>();
//addSongFromAlbumToAlbum(albums, targetAlbum, "Basket Case");
findMatchedSongs(albums, targetAlbum, "Basket Case");
for(Song matchedSong : targetAlbum) {
System.out.println(matchedSong); //outputs Song[title=Basket Case, duration=3]
}
}
private static boolean findMatchedSongs(LinkedList<LinkedList<Song>> inputAlbums, LinkedList<Song> outputAlbum, String searchedTitle) {
if (searchedTitle == null) {
System.out.println("Provide a title to search for.");
return false;
}
for (LinkedList<Song> songs : inputAlbums) {
for (Song song : songs) {
if (!searchedTitle.equals(song.getTitle())) {
continue;
}
if (outputAlbum.contains(song)) {
System.out.println(String.format("Song %s already exists in the album; please choose a different song", song.getTitle()));
return false;
}
outputAlbum.add(song);
}
}
return true;
}
}
class Album {
private Collection<Song> songs;
public Album(Collection<Song> songs) {
this.songs = songs;
}
}
class Song {
String title;
int duration;
Song(String a, int b) {
this.title = a;
this. duration = b;
}
public String getTitle() {
return title;
}
public int getDurationSeconds() {
return duration;
}
@Override
public boolean equals(Object that) {
if (that == null) {
return false;
}
if (!(that instanceof Song)) {
return false;
}
Song song = (Song) that;
if (this.title != null && !this.title.equals(song.getTitle())) {
return false;
}
if (this.duration != song.getDurationSeconds()) {
return false;
}
return true;
}
//hashCode() function omitted for brevity
@Override
public String toString() {
return String.format("Song[title=%s, duration=%d]", title, duration);
}
}
-
1Thanks that is exactly what I was trying to do. sorry for the miscomunitcation. Ill give this a shot and let you knowYHapticY– YHapticY07/31/2020 01:13:48Commented Jul 31, 2020 at 1:13
LinkedList<List<Songs>> albums
1
.