I have this map:
Map<Integer,List<EventiPerGiorno>> mapEventi=new HashMap<Integer,List<EventiPerGiorno>>();
where EventiPerGiorno is a Comparable object.
How can I get a sorted list from the map?
I tried with
Collection<List<EventiPerGiorno>> collection=mapEventi.values()
Comparable.sort(collection);
But Comparable.sort() doesn't like the list as comparable. Is there a ComparableList?
EDIT
this is the comparable method...
public class EventiPerGiorno implements Comparable<EventiPerGiorno>{
#Override
public int compareTo(EventiPerGiorno o) {
return this.getPrimoSpettacolo().compareTo(o.getPrimoSpettacolo());
}
}
Java Collections don't have any order associated with them. You could turn the Collection into a List first and then sort it.
Collection<List<EventiPerGiorno>> collection = mapEventi.values()
YourComparableList<List<EventiPerGiorno>> list = new YourComparableList(collection);
Collections.sort(list);
For this, you will need to create some sort of List that implements Comparable. See How do I correctly implement Comparable for List in this instance? for an example.
Note that this is sorting the objects of type List<EventiPerGiorno>, not the objects of type EventiPerGiorno. If you are interested in sorting the latter, you might want this instead:
ArrayList<EventiPerGiorno> bigList = new ArrayList<EventiPerGiorno>();
for (List<EventiPerGiorno> list : mapEventi.values()) {
bigList.addAll(list);
}
Collections.sort(bigList);
You are attempting to sort a List of Lists. List doesn't implement Comparable. You'll have to create your own Comparator instance.
Map<String, List<EventiPerGiorno>> map = new HashMap<String, List<EventiPerGiorno>>();
List<List<EventiPerGiorno>> lists = new ArrayList(map.values());
Collections.sort(lists, new Comparator<List<EventiPerGiorno>>() {
#Override
public int compare(List<EventiPerGiorno> o1, List<EventiPerGiorno> o2) {
// ??? This is up to you.
return 0;
}
});
This will sort every list in your map:
for (List<EventiPerGiorno> list : mapEventi.values()) {
Collections.sort(list);
}
Or if you perhaps want to retrieve a single sorted list without modifying the lists in the map:
int someKey = ...;
List<EventiPerGiorno> list = new ArrayList<>(mapEventi.get(someKey));
Collections.sort(list);
return list;
You would need to extend List and make it implement Comparable. There is no default natural ordering that can be used to compare multiple Lists.
The collections framework wouldnt know if you wanted to sort the list by number of items, number of duplicates, or values within the list.
Then to sort you use:
http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort%28java.util.List%29
Related
I know that TreeSet in java automatically sort its elements in ascending order an it guarantees the order.
for example, If i have an array of Date object in random and I copy it to TreeSet then it will be added in TreeSet in sorted way.
but suppose instead of a simple Date object, I have an ArrayList of HashMap<String,Object>, in the following format.
first value in arraylist,
{mydate = 32156464 , mystring = "abc", mystring2 = "xyz"}
2nd value in arraylist of hashmap,
{mydate = 64687678 , mystring = "abdc", mystring2 = "xyzzz"}
3rd value in arraylist of hashmap,
{mydate = 11233678 , mystring = "abxdc", mystring2 = "xyzppzz"}
Now if i want to sort this arraylist of hashmap based on mydate key, i have to create a new comparator in TreeSet instance like this,
public static Set<HashMap<String, Object>> mySet = new TreeSet<>(new Comparator<HashMap<String, Object>>() {
#Override
public int compare(HashMap<String, Object> o1, HashMap<String, Object> o2) {
return ((Date) o2.get(mydate)).compareTo((mydate) o1.get(DATE));
}
});
and it will store the arraylist inside the TreeSet in sorted order just fine. But I have used a custom Comparator to achieve this. What is the point of using TreeSet in this situation for sorting data if i am also providing a custom Comparator to it ?
How can i sort this ArrayList of HashMap based on date value without using a new instance of Comparator in TreeSet ?
What is the point of using TreeSet in this situation for sorting data if i am also providing a custom Comparator to it ?
Because it's the TreeSet code that keeps it sorted. You haven't had to provide any of the code for that - all you've had to provide is the custom comparison.
How can i sort this ArrayList of HashMap based on date value without using a new instance of Comparator in TreeSet ?
You can't, directly. You could write a subclass of HashMap which implemented Comparable for itself, but that would seem a bit odd to me. For example:
public class SpecialMap extends HashMap<String, Object>
implements Comparable<SpecialMap> {
private final String key;
public SpecialMap(String key) {
this.key = key;
}
public int compareTo(SpecialMap other) {
// TODO: Null handling
Date thisDate = (Date) this.get(key);
Date otherDate = (Date) other.get(key);
return thisDate.compareTo(otherDate);
}
}
Then you could have an ArrayList<SpecialMap> and sort that.
But given that you've had to provide basically the same code as for the comparator and bound your comparison with the map type, it feels to me like it would be better just to stick with the comparator.
If you don't supply a Comparator to the TreeSet, then it will rely on its elements being Comparable to sort them. If they're not Comparable, then a ClassCastException will result. The TreeSet javadocs explain:
A NavigableSet implementation based on a TreeMap. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.
But the HashMap class is not Comparable, so you must supply a custom Comparator so the TreeSet knows how you want to sort them. You cannot sort your HashMaps without a Comparator, whether they're in a TreeSet or any other collection.
There are advantages to using a TreeSet in this situation. The add, find, and remove operations are O(log n). If you were to use an ArrayList for this, then add and remove operations would be O(n), even if the find operation would still be O(log n).
More from TreeSet javadocs:
This implementation provides guaranteed log(n) time cost for the basic operations (add, remove and contains).
Instead of using HashMap you could create a class that contains mydate, mystring, mystring2 and implements a Comparable interface.
However it's a good practice to use comparator because you'll be able to supply sorting criteria in runtime.
The point of using a comparator in a TreeSet is that you don't have write the code to do the actual sorting, you just provide a method that determines which of your objects is first, based on your comparison rules.
If you don't want to create a comparator, you would need to add to your collection objects that implement the Comparable interface.
To sort an ArrayList, use Collections.sort().
Lets say I have an array of an array of strings:
ArrayList<ArrayList<String>> arrayOfArray= new ArrayList<ArrayList<String>>();
Maybe it could look something like this(eg.):
arrayOfArray = [[A,1,B,2],[C,1,D,2],[C,1,D,2],[A,1,B,2]]
In the end I want this(duplicates was removed):
arrayOfArrayNoDuplicates = [[C,1,D,2],[A,1,B,2]]
Then as a final step I want this array of array to be sorted on the first item in the array.
Looks like this array of array maybe was sorted on the A or the B.
arrayOfArraySorted = [[A,1,B,2],[C,1,D,2]]
Is this possible without also sorting the inner array? I want to keep the order within the array "A,1,B,2".
I hope you understand want I want to do:)
/M
You use a set
It functions like an array, it dedupes
You can use a Set with a Comparator fot that.
Set<List<String>> list = new TreeSet<ArrayList<String>>(
new Comparator<List<String>>() {
public int compare(List<String> left, List<String> right) {
//check here if equal, before or after...
}
}
);
You should really use a HashSet or similar to remove duplicates from your collection of data (sets can only contain unique elements). I'm unsure how effective this will be against ArrayList's of varying contents though, so you might be best off extending ArrayList<String> and implementing your own bool equals(Object a) method (for your inner arrays).
To then sort your collection you should using Collections.sort(), you can then pass this a custom Comparator to sort them by whichever order you please. (A comparator lets you provide a method that takes 2 objects and rates their order.) Or if you've extended ArrayList<String> simply add the compare method to your class and add implements Comparator.
An example Comparator would be;
import java.util.*;
class ALComparator implements Comparator<ArrayList<String>>
{
#Override
public int compare(ArrayList<String> a, ArrayList<String> b)
{
if(a.size()==b.size())
return 1;
if(a.size()==0)
return -1;
if(b.size()==0)
return 1;
return a.get(0).compareTo(b.get(0));
}
}
I am creating a SortedList class that implements List.
If I understand correctly, the method toArray(T[] a) takes an array of objects as a parameter and returns a sorted array of these objects.
In the java documentation we can read that if the Collection length is greater than the sortedList, a new array is created with the good size, and if the collection length is smaller than the sortedList, the object following the last object of the collection is set to null.
The project I am working on does not let me use null values in the sorted list, so I am implementing the method differently, using a new sortedList and the toArray() method:
public <T> T[] toArray(T[] a)
{
SortedList sort = new SortedList();
for(Object o : a)
{
sort.add(o);
}
return (T[])sort.toArray();
}
Would this be a good way to implement this method or should I expect errors using it like that?
Thank you for your time.
First a recommendation:
If you want SortedList to implement the List interface, it's a good idea to extend AbstractList instead of implementing List directly. AbstractList has already defined many of the necessary methods, including the one you're having problems with. Most List-implementations in the Java platform libraries also extend AbstractList.
If you still want to implement List directly, here is what the method is supposed to do:
Let a be the specified array.
If a is large enough, fill it with the elements from your SortedList (in the correct order) without caring about what was previously in a.
If there's room to spare in a after filling it, set a[size()] = null. Then the user will know where the list ends, unless the list contains null-elements.
If the list doesn't fit in a, create a new array of type T with the same size as the list, and fill the new one instead.
Return the array you filled. If you filled a, return a. If you made a new array, return the new array.
There are two reasons why this method is useful:
The array will not necessarily be of type Object, but of a type T decided by the user (as long as the type is valid).
The user may want to save memory and re-use an array instead of allocating more mamory to make a new one.
Here is how the Java Docs describe the method.
If you are implementing a "SortedList" class, it's probably in your best interest to maintain a sorted list internally, rather than relying on the toArray() method to sort them on the way out. In other words, users of the class may not use the toArray() method, but may instead use listIterator() to return an Iterator that is supposed to iterate over the elements of the list in the proper order.
Are you sure you need to implement List. It is often sufficient just to implement Iterable and Iterator.
public class SortedList<S extends Comparable<S>> implements Iterable<S>, Iterator<S> {
private final Iterator<S> i;
// Iterator version.
public SortedList(Iterator<S> iter, Comparator<S> compare) {
// Roll the whole lot into a TreeSet to sort it.
Set<S> sorted = new TreeSet<S>(compare);
while (iter.hasNext()) {
sorted.add(iter.next());
}
// Use the TreeSet iterator.
i = sorted.iterator();
}
// Provide a default simple comparator.
public SortedList(Iterator<S> iter) {
this(iter, new Comparator<S>() {
public int compare(S p1, S p2) {
return p1.compareTo(p2);
}
});
}
// Also available from an Iterable.
public SortedList(Iterable<S> iter, Comparator<S> compare) {
this(iter.iterator(), compare);
}
// Also available from an Iterable.
public SortedList(Iterable<S> iter) {
this(iter.iterator());
}
// Give them the iterator directly.
public Iterator<S> iterator() {
return i;
}
// Proxy.
public boolean hasNext() {
return i.hasNext();
}
// Proxy.
public S next() {
return i.next();
}
// Proxy.
public void remove() {
i.remove();
}
}
You can then do stuff like:
for ( String s : new SortedList<String>(list) )
which is usually all that you want because TreeSet provides your sortedness for you.
I want to sort my Listview according to some value in my application but i dont know how to code it. I researched and found that people are using comparator and collection to sort the arraylist. Basically, i want to sort by some status such as accepted or rejected. The value is store in TAG_ACCEPT_REJECT and display in R.id.applicantStatus.
Below is my code:
adapter = new SimpleAdapter(
ApplicantJobStatusActivity.this,
applicantsList,
R.layout.list_applicant_status,
new String[] { TAG_UID, TAG_NAME,
TAG_ACCEPT_REJECT,
TAG_ACCEPT_REJECT_DATETIME },
new int[] { R.id.applicantUid,
R.id.applicantName,
R.id.applicantStatus,
R.id.accept_reject_datetime });
setListAdapter(adapter);
I want to know how and where to place the sorting code using comparator and collection to rearrange my ListView.
You should sort your list applicantsList prior to passing it to your adapter. You can then use the Collections.sort approach. Something like that:
Collections.sort(applicantsList, new Comparator<T extends Map<String, ?>> {
public int compare(T map1, T map2) {
if (!map1.has(TAG_ACCEPT_REJECT)) return -1;
if (!map2.has(TAG_ACCEPT_REJECT)) return 1;
// Assumes the objects you store in the map are comparables
return map1.get(TAG_ACCEPT_REJECT).compareTo(map2.get(TAG_ACCEPT_REJECT));
}
});
- Use Arrays.sort() before assigning the Array to the Adapter.
- Or you can Use Collections.sort(Collection c) with Comparable Interface,
- Or Collections.sort(Collection c, Comparator cp) with Comparator Interface, with Colletions like ArrayListbefore assigning it to theAdapter`.
///////////////////////// Edited Part//////////////////////////
See this below link, which contains all the examples of sorting an Array, ArrayList etc using various techniques.
http://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/
In Java, I have a Set, and I want to turn it into a sorted List. Is there a method in the java.util.Collections package that will do this for me?
The answer provided by the OP is not the best. It is inefficient, as it creates a new List and an unnecessary new array. Also, it raises "unchecked" warnings because of the type safety issues around generic arrays.
Instead, use something like this:
public static
<T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
List<T> list = new ArrayList<T>(c);
java.util.Collections.sort(list);
return list;
}
Here's a usage example:
Map<Integer, String> map = new HashMap<Integer, String>();
/* Add entries to the map. */
...
/* Now get a sorted list of the *values* in the map. */
Collection<String> unsorted = map.values();
List<String> sorted = Util.asSortedList(unsorted);
Sorted set:
return new TreeSet(setIWantSorted);
or:
return new ArrayList(new TreeSet(setIWantSorted));
Here's how you can do it with Java 8's Streams:
mySet.stream().sorted().collect(Collectors.toList());
or with a custom comparator:
mySet.stream().sorted(myComparator).collect(Collectors.toList());
List myList = new ArrayList(collection);
Collections.sort(myList);
… should do the trick however. Add flavour with Generics where applicable.
Always safe to use either Comparator or Comparable interface to provide sorting implementation (if the object is not a String or Wrapper classes for primitive data types) .
As an example for a comparator implementation to sort employees based on name
List<Employees> empList = new LinkedList<Employees>(EmpSet);
class EmployeeComparator implements Comparator<Employee> {
public int compare(Employee e1, Employee e2) {
return e1.getName().compareTo(e2.getName());
}
}
Collections.sort(empList , new EmployeeComparator ());
Comparator is useful when you need to have different sorting algorithm on same object (Say emp name, emp salary, etc). Single mode sorting can be implemented by using Comparable interface in to the required object.
There's no single method to do that. Use this:
#SuppressWarnings("unchecked")
public static <T extends Comparable> List<T> asSortedList(Collection<T> collection) {
T[] array = collection.toArray(
(T[])new Comparable[collection.size()]);
Arrays.sort(array);
return Arrays.asList(array);
}
You can convert a set into an ArrayList, where you can sort the ArrayList using Collections.sort(List).
Here is the code:
keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);
Collections.sort(list);
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);
list.addAll(sortedset);
where originalset = unsorted set and list = the list to be returned
#Jeremy Stein I wanted to implement same code. As well I wanted to sort the set to list, So instead of using Set I converted set values into List and sort that list by it's one the variable.
This code helped me,
set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());
I am using this code, which I find more practical than the accepted answer above:
List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));