3

The situation I have is that I currently have a LinkedList of 'Appointment' objects which have the following attributes:

'patient' 'date' 'type'

The only functionality required is to loop through this LinkedList and display each appointment in order of 'date'. So, each time a new Appointment is created (using a method called 'addAppointment' in the same class as the LinkedList of appointments), the method will sort the linked list using a Comparator.

However, I was wondering if this is bad practice and if there is a better way to do this? I never need to get the 'Appointment' object by its index and so would it be better practice to use a Priority Queue?

8
  • possible duplicate of A good Sorted List for Java Commented Mar 19, 2014 at 20:29
  • I also forgot to add that the attributes may need to be modified, like if an appointment changes date or type. Commented Mar 19, 2014 at 20:30
  • @ElliottFrisch In this case, the elements are all going to be distinguishable, and I think SortedSet makes the most sense. Commented Mar 19, 2014 at 20:30
  • @chrylis I don't disagree, but that's an interface. I assume you mean TreeSet. Commented Mar 19, 2014 at 20:32
  • @ElliottFrisch No not really a duplicate. This Question is about maintaining a sorted order by field on the objects. That other Question is about random access to an element in the set. Commented Mar 31, 2024 at 23:20

4 Answers 4

1

I would disagree with everyone here so far and say go ahead and use a simple ArrayList. Your main use case is just to loop through the list and display it in order, right? You can sort an array list by using the Collections.sort() method, which will sort any list of objects implementing Comparable. So just implement Comparable in your Appointment object (only need to provide a .compareTo() method...the API explains this well, or the Java Trail on Collections) and your sorting will then be painless and easy. My experience is this is better performing than an object like TreeSet or a LinkedList.

Now those would be better performing if you were always inserting into the middle of the list a lot, but you seem to mostly be reading this list from what you said, so go for the ArrayList.

Sign up to request clarification or add additional context in comments.

3 Comments

This very good method indeed for sets of objects that you need to sort for example only a few times per program run. The problem with TreeMap or similar containers is that they pretty much sort the list every time you add a new entry there.
I do need to sort the list every time I add a new entry because the application requires new Appointment objects to be created in run-time and then added to the list.
ArrayList may not be best then. TreeSet may be better. It may also be meaningless. Adding to a TreeSet does maintain sorted order, but I would consider how often the list is simply read versus how often items get added. If there are enough additions, you may see better performance with TreeSet, once you get enough items (we're talking a lot). Sorting with Collections.sort() is O(n log n). Adding to a TreeSet is O(log n). By the way if you do use TreeSet, watch out how you implement hashcode and equals. If you only compare items on date, two items with same date will overwrite each other.
1

NavigableSet

The NavigableSet, and its predecessor, SortedSet, define a contract for a distinct (no duplicates allowed) collection of objects maintained in a certain order.

The TreeSet class bundled with Java implements this interface. For concurrency, or for very large collections, use ConcurrentSkipListSet.

You said:

'Appointment' objects which have the following attributes: 'patient' 'date' 'type'

record Appointment ( String patient , LocalDate date , String type ) {}

Define a Comparator to control the sorting. We pass a method reference to access the member field by which we want to sort. In our example that is the LocalDate field named date.

Comparator < Appointment > comparator = Comparator.comparing( Appointment :: date );

Track our appointments. Specify the comparator to use automatically as elements added to this set.

NavigableSet < Appointment > appointments = new TreeSet <>( comparator );

Sample data.

appointments.addAll(
        List.of(
                new Appointment( "Alice" , LocalDate.of( 2025 , Month.APRIL , 23 ) , "trim" ) ,
                new Appointment( "Bob" , LocalDate.of( 2025 , Month.JANUARY , 23 ) , "dye" ) ,
                new Appointment( "Carol" , LocalDate.of( 2025 , Month.MARCH , 23 ) , "set" )
        )
);

Add another element.

appointments.add(
        new Appointment( "Davis" , LocalDate.of( 2025 , Month.FEBRUARY , 23 ) , "cut" )
);

See results.

System.out.println( "appointments = " + appointments );

appointments = [Appointment[patient=Bob, date=2025-01-23, type=dye], Appointment[patient=Davis, date=2025-02-23, type=cut], Appointment[patient=Carol, date=2025-03-23, type=set], Appointment[patient=Alice, date=2025-04-23, type=trim]]

Sure enough, the Appointment objects are kept in sorted order, arranged by the date.

You might want a secondary sort, to order any multiple appointments for the same date.

Comparator < Appointment > comparator =
        Comparator
                .comparing( Appointment :: date )
                .thenComparing( Appointment :: patient );

Sequenced collections

In Java 21+, we have sequenced collections, adding more interfaces to the Java Collections Framework. These interfaces include:

NavigableSet, SortedSet, TreeSet, and ConcurrentSkipListSet all extend/implement those two new interfaces.

SequencedCollection < Appointment > appointments = new TreeSet <>( comparator );

class hierarchy diagram by Stuart Marks of Oracle Corp.

Comments

0

Generally speaking, use an ArrayList when you need random access and a LinkedList when there will be lots of inserts and removes. If you need a data structure that stays sorted, PriorityQueue is an option, but it's really intended for the scenario where you're just pulling the top element off sequentially. If you're needing to repeatedly iterate over the elements, use a SortedSet.

If a field involved in the element's ordering changes after it's inserted into any sorted collection, you should remove and re-add the element (preferably removing before modification).

3 Comments

A SortedSet will be fine as long as "duplicates" are not allowed however
Generally speaking never use LinkedList. There are many cases where ArrayList outperforms LinkedList for many inserts and removals, at least when iteration is also required, as here. Perhaps counterintuitively.
PriorityQueue …'s really intended for the scenario where you're just pulling the top element off sequentially. Very correct. java.util.PriorityQueue won’t work for looping in date order (without exhausting the queue).
-1

Use a PriorityQueue

Write a compareTo method for your Appoitnment object that specifies the natural ordering according to date.

PriorityQueue<Appointment> schedule = new PriorityQueue<Appoitnment>();
Appointment a1 = new Appointment();
Appointment a2 = new Appointment();
schedule.add(a1);
schedule.add(a2);

// Iteratively removes the earliest appointment remaining in the schedule
while (schedule.peek != null) {
  System.out.println(schedule.poll().toString());
}

1 Comment

java.util.PriorityQueue is only partially sorted and unsuited for looping through in sort order (which I understood as a requirement in the question: loop through this LinkedList and display each appointment in order of 'date'.).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.