Reputation: 822
I need to write a static method in a class MinTester that computes the "smallest" string from an ArrayList collection using a comparator object:
public static String min(ArrayList<String> list, Comparator<String> comp)
I cannot use the Collections class to compute the minimum.
Here is what I have so far.
public class MinTester
{
public static String min(ArrayList<String> list, Comparator<String> comp)
{
String shortest = list.get(0);
for(String str : list) {
if ( comp.compare(str, shortest) < 0) {
shortest = str;
}
}
return shortest;
}
}
I am not getting any errors here from the method, So I try to test it in Main with this. I get this error when trying to pass comp: Variable comp may not have been initialized
public static void main(String[] args)
{
// TODO code application logic here
MinTester s = new MinTester();
Comparator<String> comp;
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
String a = s.min(list,comp);//Error: Variable comp may not have been initialized
System.out.println(a);
}
Heres where I run into my problem.
I try
Comparator<String> comp = new Comparator<>();//Error:Comparator is abstract, cannot be instantiated
Comparator<String> comp = new MinTester();//Error: MinTester cannot be converted to Comparator<String>
Can anyone tell me the proper way to handle this Comparator? Im not sure if Im just trying to initialize it incorrectly, or if I'm missing something in my MinTester class.
Upvotes: 3
Views: 30305
Reputation: 34573
Comparator
is an interface; different classes can implement it in different ways to perform different kinds of comparisons. The reason why your method takes a Comparator
is so that the caller can choose how the strings should be compared. Pass in a Comparator
that does lexical (aka alphabetical) comparison, and you'll get the first string in lexical order. Pass in a Comparator
that looks at string length, and you'll get the shortest string.
Since the String
class already implements the Comparable
interface — a sort of sibling to Comparator
that lets a class define its own comparison method — here's a handy generic class that lets you use any Comparable
through the Comparator
interface:
public final class ComparableComparator<T extends Comparable<T>> implements Comparator<T> {
@Override
public int compare(final T a, final T b) {
return a.compareTo(b);
}
}
Pass one of those into your method and it'll compare the strings using the String
class's own compareTo
method.
Edit: In Java 8 or later, the Comparator.naturalOrder()
method gives you the same thing, so you don't need to write the class above.
Upvotes: 1
Reputation: 85789
You should write a class that implements Comparator<String>
for this. A quick approach using anonymous class:
String a = s.min(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
Since you need to compare based on String length, just change the comparison logic in the compare
method:
String a = s.min(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return (s1.length() > s2.length()) ? 1 : (s1.length() < s2.length()) ? -1 : 0;
}
});
If you happen to use Java 7, then use Integer#compare
:
String a = s.min(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
If you use Java 8, you can use a lambda expression:
String a = s.min(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
Upvotes: 5
Reputation: 534
You do not need to use Comparator
, at least not unless you want to modify the natural ordering of the string comparisons. Use the compareTo()
method for the String
class instead.
if (str.compareTo(shortest) < 0) {
shortest = str;
}
If at all you wish to modify the natural ordering, you can create a class which implements the Comparator
interface and then pass an instance of this class to the compare()
method. You can also define your own logic for the comparisons.
public class StringDescComparator implements Comparator<String> {
@Override
public int compare(String str1, String str2) {
// return str1.compareTo(str2); // For natural ordering
return -1 * str1.compareTo(str2); // For reversed ordering
}
}
Then you can use an instance of the above class to compare in the descending order such that: "b" < "a"
Comparator comp = new StringDescComparator();
Upvotes: -1