Extreme Java newb ie здесь. Я делаю несколько простых упражнений, чтобы немного попрактиковаться с базовыми c концепциями языка.
В одном из этих упражнений мне предлагается реализовать класс MusicAlbum, который, среди прочего, имеет один его экземпляров атрибутов - список экземпляров класса MusicTrack.
Поскольку каждый MusicTrack должен быть уникально идентифицирован по его идентификатору, и с учетом того, что указано, что указанный список должен быть «отсортирован» (хотя нет реального указания на это), я выбрал TreeSet.
Так что я реализовал Comparable в классе MusicTrack, чтобы набор MusicAlbum был отсортирован по идентификаторам экземпляров MusicTrack, которые он содержит. Кроме того, два экземпляра MusicTrack с одинаковым идентификатором будут считаться одним и тем же экземпляром MusicTrack, и в дереве не будет дубликатов. Пока все хорошо (или, по крайней мере, я так думаю).
Проблема возникает, когда упражнение просит сделать класс MusicAlbum повторяемым в порядке убывания продолжительности (что является еще одним атрибутом класс MusicTrack).
Я сразу подумал изменить метод CompareTo, чтобы сортировка набора деревьев вместо этого была организована по длительности, в то время как переопределение метода equals класса Object по-прежнему гарантировало бы уникальность Я бы. Тем не менее, это не сработало, похоже, что существование метода CompareTo делает метод equals совершенно неуместным.
Итак, вот мой вопрос: можно ли отсортировать набор деревьев по критериям и сохранить уникальность в этом тот же набор деревьев с совершенно другими критериями?
Я нашел эту цитату, которая может предположить, что такая вещь, если вообще возможно, все еще не рекомендуется:
Обратите внимание, что порядок поддерживается по отсортированной карте (независимо от того, предоставлен или нет явный компаратор) должен быть согласован с equals, если эта отсортированная карта должна правильно реализовывать интерфейс Map. (См. Comparable или Comparator для точного определения соответствия с equals.) Это так, потому что интерфейс Map определен в терминах операции equals, но карта выполняет все ключевые сравнения, используя свой метод CompareTo (или сравнение), поэтому два ключа которые считаются равными этим методом, с точки зрения отсортированной карты равны. Поведение отсортированной карты четко определено, даже если ее порядок не совпадает с равенством; он просто не соблюдает общий контракт интерфейса Map.
Однако информация, которую я нашел по этому поводу, меня довольно смущает, поэтому я прошу разъяснений.
Также, что может быть хорошим способом решить это упражнение? Конечно, вот что мне удалось сделать до сих пор:
MusicTrack. java
public class MusicTrack implements Comparable<MusicTrack> {
private static int nextId = 0;
private int id;
private String title;
private String author;
private int duration;
@SuppressWarnings("serial")
public class NegativeDurationException extends Exception {
public NegativeDurationException() {
System.err.println("Duration value must be greater than 0.");
}
}
public MusicTrack(String title, String author, int duration) throws NegativeDurationException {
if(duration < 1) {
throw new NegativeDurationException();
}
else {
this.id = nextId++;
this.title = title;
this.author = author;
this.duration = duration;
}
}
public int getId() {
return this.id;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getDuration() {
return this.duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String toString() {
return "Id: " + this.id + "\nAuthor: " + this.author + "\nTitle: " + this.title + "\nDuration: " + this.duration + "\n";
}
@Override
public int compareTo(MusicTrack track) {
return this.id - track.id;
}
}
MusicAlbum. java
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class MusicAlbum implements Iterable<MusicTrack> {
public enum PhysicalMedia {
VYNIL, CD, USB
}
private static int nextId = 0;
private int id;
private String title;
private String author;
private Date purchaseTime;
private Set<MusicTrack> tracks;
private PhysicalMedia physicalMedia;
public MusicAlbum(String title, String author, String purchaseTime, PhysicalMedia physicalMedia) {
try {
this.purchaseTime = new SimpleDateFormat("dd/mm/yyyy").parse(purchaseTime);
}
catch (ParseException e) {
e.printStackTrace();
}
this.id = nextId++;
this.title = title;
this.author = author;
this.physicalMedia = physicalMedia;
this.tracks = new TreeSet<MusicTrack>();
}
public void addMusicTracks(MusicTrack ... tracks) {
for(MusicTrack track: tracks) {
this.tracks.add(track);
}
}
public boolean contains(MusicTrack track) {
return this.tracks.contains(track);
}
public int getTotalDuration() {
Iterator<MusicTrack> i = this.tracks.iterator();
int totalDuration = 0;
while(i.hasNext()) {
totalDuration += i.next().getDuration();
}
return totalDuration;
}
public String toString() {
return "Id: " + this.id + "\nDate: " + this.purchaseTime.toString() + "\nTotal duration: " + this.getTotalDuration();
}
@Override
public Iterator<MusicTrack> iterator() {
return this.tracks.iterator();
}
}