Reputation: 337
I have created a To-Do-List program where one of the actions requires the program to list all tasks input by the user in ascending order of the date that they fall on.
Output example:
Tasks listed in ascending order (earliest first):
TaskName, 20/04/2020, time, location, duration, category
TaskName, 18/07/2020, time, location, duration, category
TaskName, 09/08/2020, time, location, duration, category
TaskName, 21/12/2020, time, location, duration, category
So far, with the code that I have, the tasks that the user input all list, but they don't list in ascending order of the date of each task.
Here is my code so far:
public void sortTasks() {
System.out.println("Sorted tasks by date (earliest first): ");
Collections.sort(currentList);
currentList.forEach(System.out::println);
}
}
Upvotes: 0
Views: 1015
Reputation: 29282
It would be better if you just maintain a List
of Task
instances and sort that List
.
You can use one of the following options to sort a List
of Task
instances:
To implement Comparable
interface, you must override compareTo
method in Task
class. Since you want to sort Tasks based on date
instance field, you can just return the result of date comparison.
Here's how you should override compareTo()
method to sort Tasks in ascending order based on date
instance field.
@Override
public int compareTo(Task o) {
return this.date.compareTo(o.date);
}
Since Date
class already implements Comparable
interface, you can just call compareTo
method to compare two Date
instances.
Now to sort the list of tasks, call sort
method of Collections
class.
Collections.sort(taskList);
Here's a version of your code that implements Comparable
interface and sorts the tasks using date
instance field
There are more than one ways to sort objects using a Comparator
interface:
Comparator
interfaceYou can create a class that implements Comparator
interface and then override compare
function. Implementation of compare
function will be same as that of compareTo
function implemented above by implementing Comparable
interface.
class TaskComparator implements Comparator<Task> {
@Override
public int compare(Task o1, Task o2) {
return o1.getDate().compareTo(o2.getDate());
}
}
To sort the task list, you have two options:
Use sort
function of Collections
class and pass an instacne of TaskComparator
class as a second argument
Collections.sort(taskList, new TaskComparator());
Use sort
method of List
interface
taskList.sort(new TaskComparator());
Here's a version of your code that creates a separate comparator class to sort the tasks using date
instance field
Instead of creating a separate class to implement Comparator
interface, you can use an anonymous class
Collections.sort(taskList, new Comparator<Task>() {
@Override
public int compare(Task t1, Task t2) {
// code to compare Task objects
}
});
or
taskList.sort(new Comparator<Task>() {
@Override
public int compare(Task o1, Task o2) {
return o1.getDate().compareTo(o2.getDate());
}
});
Java 8 introduced lambda expressions, you can replace anonymous class with lambda expression to make your code concise
Collections.sort(taskList, (o1, o2) -> o1.getDate().compareTo(o2.getDate()));
or
taskList.sort((o1, o2) -> o1.getDate().compareTo(o2.getDate()));
Here's a version of your code that uses lambda expression to implement Comparator
interface
You can also use static method named comparing
of Comparator
interface. It will return a comparator that will be used for sorting.
Collections.sort(taskList, Comparator.comparing(Task::getDate));
or
taskList.sort(Comparator.comparing(Task::getDate));
Here's a version of your code that uses Comparator.comparing
method to sort the tasks using date
instance field
For details on how to implement Comparable
or Comparator
interfaces, see:
Upvotes: 0
Reputation: 1800
First of all you need to store Task
objects not String
in your list.
Usually you can pass a Comparator
to Collections.sort
.
Collections.sort(tasks, Comparator.reverseOrder());
In order for that to work properly you have to make Task
an implementation of Comparable
, the way you compare the fields of the object depend on your specific task, here you can provide implementation for ascending comparison, and than reverse it by reverseOrder
method.
class Task implements Comparable<Task> {
...
@Override
public int compareTo(Task task) {
return Comparator
.comparing(Task::getTitle)
.thenComparing(Task::getDate)
.compare(this, task);
}
}
Alternately, you can create and pass to sort
a more sophisticated Comparator
object, without Task
being a Comparable
object.
Note though, that this approach makes code less reusable.
Collections.sort(tasks,
Comparator
.comparing(Task::getTitle)
.thenComparing(Task::getDate)
.reverseOrder()
);
Also consider using SortedSet
or PriorityQueue
instead of List
for your task in order to avoid explicit sorting and reduce algorithmic complexity
Upvotes: 2
Reputation: 1374
Since creating TaskList and sorting based on dates solution is already provided by @Amongalen.
I will provide a different approach with better Time complexity. Since Sorting a collection can be O(nlogn). It is not a good idea to sort after every time you add an element to the list.
Instead you can maintain a PriorityQueue
of Task Object and compare them based on date and add Task
objects to that PriorityQueue
.
Now you don't need to call sort, just iterate
over the queue
and display the result.
PriorityQueue<Task> queue = new PriorityQueue<>((o1,o2)-> o1.getDate.comapreTo(o2.getDate));
// Add task object to the queue
queue.add(myTaskObject);
//iterate and display when asked
Iterator<Task> it = queue.iterator();
while(it.hasNext()) {
System.out.println(it.next().toString());
}
Note: adding task object to queue is O(logn) So this will improve time of your solution
Upvotes: 0
Reputation: 4471
You can sort List
use sort
method with custom Comparator
list.sort(Comparator.comparing(Task::getDate).reversed());
But I think you have to use another collection. PriorityQueue
feet better than ArrayList
.
Queue<Task> queue = new PriorityQueue<>(Comparator.comparing(...));
Upvotes: 0
Reputation: 3131
Your current approach to the problem makes it hard to achieve what you want. You have a list of Strings and want to parse some fragment of them and sort based on that. It is possible but you can make it much simplier. You already got a dedicated class to represent your Task
. You should keep a List
of Task
s then, not their String representations.
When you have a List<Task>
, there are couple of ways to sort it. You can either implement Comparable
in your class or use a Comparator
. You could do something like that:
currentList.sort(Comparator.comparing(Task::getDate))
Or (depending on desired order)
currentList.sort(Comparator.comparing(Task::getDate).reversed())
And then you use getItem()
only when you want to print the results (such method is usually called toString()
).
Upvotes: 5