How to write custom comparator in java?

Tags: , ,



I want to store key-value pairs in TreeMap and sort the entries based on the value of key as per the following logic:

  1. “type” (case insensitive) key should be at first.
  2. the key start with “metadata” (case insensitive) should be at last in ascending order
  3. rest of the keys(case insensitive) should be in middle in ascending order

I am using Java 8 version.

Program:

public class CustomeCamarator  {
    public static void main(String[] args) {
        CustomComparator comparator = new CustomComparator();
        Map<String,Object> empData=new TreeMap<>(comparator);
        empData.put("name","someName");
        empData.put("DOB","someDOB");
        empData.put("address","someAddress");
        empData.put("type","employee data");
        empData.put("ContactNo.","someContactNumber");
        empData.put("metadata.source","someMetaDataSource");
        empData.put("metadata.location","someMetaDataLocation");
        empData.put("metadata","someMetaData");
        System.out.println(empData);
        System.out.println(empData.containsKey("metadata"));//should be true but showing false
    }
}
class CustomComparator implements Comparator<String>{
    @Override
    public int compare(String o1, String o2) {
        String str1 = o1.toLowerCase();
        String str2 = o2.toLowerCase();
        if(str1.equalsIgnoreCase("type")) {
            return -1;
        }else if(!str1.contains("metadata") && !str2.contains("metadata")) {
            return str1.compareTo(str2);
        }else if(o1.contains("metadata") && !o2.contains("metadata")) {
            return 1;
        }else if(!o1.contains("metadata") && o2.contains("metadata")) {
            return -1;
        }else {
            return 1;
        }
    }
}





**Expected Output like this:**
type: someType
address: someAddress
ContactNo: someContactNumber
DOB: someDOB
name: someName
metadata: someMetaData
metadata.location: someMetaDataLocation
metadata.source: someMetaDataSource

Answer

I think the following covers your cases

public class CustomComparator implements Comparator<String> {
  @Override public int compare(String left, String right) {
    left = left.toLowerCase();
    right = right.toLowerCase();
    final int LEFT = -1;
    final int RIGHT = 1;
    // exact match!
    if (left.equals(right)) return 0;
    // not identical, so consider 'type' match
    if ("type".equals(left)) return LEFT;
    if ("type".equals(right)) return RIGHT;
    // at this point we know neither matches 'type' so lets check for 'metadata' prefix
    if (left.startsWith("metadata")) {
      // if both start with metadata use natural ordering
      if (right.startsWith("metadata")) return left.compareTo(right);
      // only left starts with 'metadata' so right comes first
      else return RIGHT;
    }
    // only right starts with 'metadata' so left comes first
    if (right.startsWith("metadata")) return LEFT;
    // at this point we know they are not equal but neither contains 'text' nor starts with 'metadata' so use natural ordering
    return left.compareTo(right);
  }
}


Source: stackoverflow