需求:将指定数据中的数据,按照字母中包含的数字大小进行排序

测试代码:

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("QW34");
    list.add("QW21");
    list.add("QW12");
    list.add("QS34");
    list.add("QW45");

    // 自定义比较器,按指定顺序排序
    Comparator<String> comparator = new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            // 定义排序规则
            if (s1.contains("QW") && s2.contains("QW")) {
                String qw1 = s1.split("QW")[1];
                String qw2 = s2.split("QW")[1];
                int i1 = Integer.parseInt(qw1);
                int i2 = Integer.parseInt(qw2);
                if (i1 > i2) {
                    return 1;
                } else if (i1 < i2) {
                    return -1;
                } else {
                    return 0;
                }
            } else {
                return 1;
            }
        }
    };
   
    TreeSet<String> strings = new TreeSet<>(comparator);
    strings.addAll(list);

    // 使用自定义比较器对集合进行排序
   // Collections.sort(list, comparator);

    // 输出排序结果
    for (String s : strings) {
        System.out.println(s);
    }
}

Comparator介绍

Comparator接口中最重要的方法是compare,它接受两个参数并返回一个整数值,用于表示两个对象的比较结果。如果返回负数,表示第一个参数应该排在第二个参数之前;如果返回正数,表示第一个参数应该排在第二个参数之后;如果返回0,表示两个参数相等,顺序不变。

TreeSet的add方法是如何调用比较器的呢

查看add方法源码可以看到

treeSet的底层用的是的Map的put方法

public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}

继续查看put方法

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
    	//这个方法会调用自定义的比较器
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}

put方法中的compare方法

final int compare(Object k1, Object k2) {
    //会判读你是否自定义了比较器,如果如果自定义了比较器,则会先试用自定义的比较器进行比较
    return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);
    //那如果没有定义比较器,则会使用对象对应类的类型默认的比较方法,比如String类中的compareTo方法
}

注意

TreeSet<Blog> stringTreeSet = new TreeSet<>();
stringTreeSet.add(new Blog());

如果添加的是对象,对象也没有实现comparable接口,则会报错

Java中的Comparator自定义排序_比较器