Reputation: 1594
Example:
Our list contains 5 names: Kevin, Hans, Fritz, Han Solo, Peter
And I now want to have all the names that contain "Han" at the top.
So the sorted list would look like that:
Hans, Han Solo, Kevin, Fritz, Peter
What I have tried so far:
Nothing because i have no clue, but i already googled and didn't find anything.
Deleting/adding items from/to the list is not an option becaue i am using the list in a CheckListView
(ControlsFX component) where each item has a checked state which would get lost.
Upvotes: 4
Views: 8240
Reputation: 21799
You can use a Comparator to specify how the sorting should work.
This solution really just moves elements containing "Han" to the front of the list - while keeping the original order between these elements (as it was defined in the desired output) - and it does not sort elements not containing "Han" as the question states: "And I now want to have all the names that contain "Han" at the top."
List<String> names = Arrays.asList("Kevin", "Hans", "Fritz", "Han Solo", "Peter"));
names.sort(getMoveToFrontComparator("Han"));
System.out.println(names);
...
private Comparator<String> getMoveToFrontComparator(String part) {
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
boolean containsFirst = o1.contains(part);
boolean containsSecond = o2.contains(part);
// Match vs No-Match: Match has the priority
if(containsFirst && !containsSecond)
return -1;
if(!containsFirst && containsSecond)
return 1;
// Match vs Match or No-Match vs No-Match: no sorting is needed
return 0;
}
};
}
The output is:
[Hans, Han Solo, Kevin, Fritz, Peter]
Note: If you want to sort the "matching vs matching" and the "non-matching vs non-matching" case, you can replace return 0;
with return o1.compareTo(o2);
.
Upvotes: 0
Reputation: 82461
In java 8 you can create Comparator
s based on a function applied to the element. Also there are methods to reverse the order produced by a comparator and chain comparators.
This allows a relatively simple creation of a comparator using the existence of a substring as primary sort criterion and the String
sorting as secondary criterion. Note that depending on your requirements the second part (.thenComparing(Comparator.naturalOrder())
) may not be necessary:
final String part = "Han";
Comparator<String> comparator = Comparator.<String, Boolean>comparing(s -> s.contains(part)).reversed()
.thenComparing(Comparator.naturalOrder());
The result of sorting your items with this Comparator
is
Han Solo, Hans, Fritz, Kevin, Peter
Upvotes: 7
Reputation: 2759
For this you need to use a Comparator<String>
.
When comparing two Strings
lets call them name1
and name2
, if name1
contains "Han"
then you return -1
indicating that name1
should come first. If name2
contains "Han"
then you return 1
indicating that name2
should come first. Otherwise neither String contains "Han"
so you return 0
which indicates that they should not be swapped. Note: this does not alphabetically sort the Strings that contain "Han"
as you did not specify this in your requirements.
In Java 8 this is simple:
List<String> names = Arrays.asList("Kevin", "Hans", "Fritz", "Han Solo", "Peter");
names.sort((name1, name2) ->
name1.contains("Han") ? -1 :
name2.contains("Han") ? 1 :
0
);
System.out.println(names);
Output:
[Han Solo, Hans, Kevin, Fritz, Peter]
Upvotes: 0
Reputation: 26961
just use Comparator
and define your own compare method with your conditions:
public static void main(String[] args) {
List<String> names = Arrays.asList("Kevin,Hans,Fritz,Han Solo,Peter".split(","));
Collections.sort(names, new Comparator<String>() {
final String PREFIX = "Han";
@Override
public int compare(String a, String b) {
if (a.contains(PREFIX) && b.contains(PREFIX)) return a.compareTo(b);
if (a.contains(PREFIX) && !b.contains(PREFIX)) return -1;
if (!a.contains(PREFIX) && b.contains(PREFIX)) return 1;
return 0;
}
});
for (String n : names) {
System.out.println(n);
}
}
OUTPUT (IMHO Han Solo
must be prior to Hans
because space
is prior to s
but you can easily modify my proposed conditions)
Han Solo
Hans
Kevin
Fritz
Peter
Upvotes: 4