Java函数式接口之Comparable

Java函数式接口之Comparable

-able接口 在Java中一般表示能力,例如Comparable 比较能力,Iterable迭代能力等等

1. Comparable接口

Comparable接口,如其名,实现它后,实现类具有比较比较能力。在Java中是一个FunctionalInterface接口,里面包含一个compareTo方法

这里引入源代码来分析, 具体如下:

  1. 实现该接口的每个类对象会被强加一个总排序,被称之为自然排序,compareTo方法被称之为自然排序法
  2. List、Array等对象实现了该接口,可以自动排序。
  3. compareTo禁止接收null值 会抛出空指针异常,null不是任何类的实例
  4. 强烈推荐自然排序和equal结果是一致的,例如 compareTo一致相当于equal方法返回true,但未要求
  5. compareTo 使用特定对象来比较顺序 返回 一个负数 或者 0 或者正数 来表示 小于 等于 大于
  6. compareTo必须满足交换性、传递性等特性
  7. 排序输出默认是升序

public interface Comparable<T> {
    
    /**
     * 使用特定对象来比较顺序 返回 一个负数 或者 0 或者正数 来表示 小于 等于 大于
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     * 必须确保交换性 x.compareTo(y)的结果和y.compareTo(x)结果一致
     * <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
     * -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>x.compareTo(y)</tt> must throw an exception iff
     * <tt>y.compareTo(x)</tt> throws an exception.)
     * 传递性
     * <p>The implementor must also ensure that the relation is transitive:
     * <tt>(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0)</tt> implies
     * <tt>x.compareTo(z)&gt;0</tt>.
     * 
     * <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
     * implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
     * all <tt>z</tt>.
     * 强烈推荐 x.compareTo比较相同的话 equals值也相等
     * <p>It is strongly recommended, but <i>not</i> strictly required that
     * <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>.  Generally speaking, any
     * class that implements the <tt>Comparable</tt> interface and violates
     * this condition should clearly indicate this fact.  The recommended
     * language is "Note: this class has a natural ordering that is
     * inconsistent with equals."
     * 一般来说 返回值 通常定义三种 -1、0或者 1 这类似一种约定 当然你负数 正数其他值也可以
     * <p>In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.
     *
     * @param   o the object to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *          is less than, equal to, or greater than the specified object.
     *
     * @throws NullPointerException if the specified object is null
     * @throws ClassCastException if the specified object's type prevents it
     *         from being compared to this object.
     */
    public int compareTo(T o);
}
1. 已实现Comparable接口
  1. List集合,一般排序借助于Collections工具类
public static void listSort(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(8);
        list.add(3);
    	//第一种排序方法
       	list.sort(null);
    	//第二种排序方法 底层使用第一种方法
        Collections.sort(list);
        System.out.println(list);
    }
  1. Array排序 一般排序借助于Arrays工具类
  //在原有基础上排序
public static void arraySort(){
        int[] arr = {1,5,3,7};
    	//第一种排序
        Arrays.sort(arr);
    	//第二种排序
    	int[] newArr = Arrays.stream(arr).sorted().toArray();
        System.out.println(Arrays.toString(arr));
    }

2. Comparator类

Comparator,一个比较的功能类,也是一个FunctionalInterface.提供了compare方法,接受两个参数,并返回比较值,比较值的规则和Comparable一致,

也可以实现Comparable相同的比较效果

//其他方法省略
@FunctionalInterface
public interface Comparator<T> {
    /**比较两个参数顺序 返回 负数 0 或 正数 分别表示 小于 等于 大于
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.<p>
     * 一般用 -1 0 1表示返回结果
     * In the foregoing description, the notation
     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
     * <i>expression</i> is negative, zero or positive.<p>
     *
     * The implementor must ensure that <tt>sgn(compare(x, y)) ==
     * -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
     * implies that <tt>compare(x, y)</tt> must throw an exception if and only
     * if <tt>compare(y, x)</tt> throws an exception.)<p>
     *
     * The implementor must also ensure that the relation is transitive:
     * <tt>((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
     * <tt>compare(x, z)&gt;0</tt>.<p>
     *
     * Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
     * implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
     * <tt>z</tt>.<p>
     *
     * It is generally the case, but <i>not</i> strictly required that
     * <tt>(compare(x, y)==0) == (x.equals(y))</tt>.  Generally speaking,
     * any comparator that violates this condition should clearly indicate
     * this fact.  The recommended language is "Note: this comparator
     * imposes orderings that are inconsistent with equals."
     *
     * @param o1 the first object to be compared.
     * @param o2 the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
     * @throws NullPointerException if an argument is null and this
     *         comparator does not permit null arguments
     * @throws ClassCastException if the arguments' types prevent them from
     *         being compared by this comparator.
     */
    int compare(T o1, T o2);
}

3. Comparable和Comparator区别

Java设计了Comparable接口,那么为什么还需要设计Comparator接口呢,两者区别是什么呢。

首先Comparable接口和Comparator接口 都能提供比较能力并返回结果。这是他们的相同点,这是设计的初衷

不同点:

  1. Comparable 表示一种能力,一般需要对象实现其接口,使其获取比较的能力。实现后 相当于本身具有比较能力。直接调用compareTo方法
  2. Comparator 是一种工具,通过这种工具,可以将两种不具备比较的对象,区分出顺序。是借助外部工具

4. Java设计方式思考

Java中有其实还有其他类似的设计。例如Iterable和iterator.都是这样。针对相同的能力尽可能的提供更多的渠道,可以实现它,或者使用工具,最终的目的都是达到需要实现的目的。根据这种类似案例,是否以后在开发业务或工具时,也提供更多的渠道供其他调用者使用

5. 其他类似案例

Iterable和Iterator

6. 总结

本篇文章其实是FunctionalInterface函数式接口的扩展。在常用的Supplier、Consumer、Function、Predicate的FunctionalInterface以及各种类型扩展后。介绍了Comparable接口。并扩展介绍Comparable的功能含义以及Comparable和Comparator比较。

其实本篇在介绍Comparable接口功能时,列举的案例,输出结果都是都是升序的,那么你有没有想过,如果列举出倒序的结果呢,又有哪几种方式呢?

<think>好的,用户现在问的是Java中的TreeMap函数接口。首先,我需要确认用户的具体需求。他之前已经询问过关于我是谁的问题,现在转向Java的TreeMap,可能是在学习Java集合框架,或者在开发中遇到了相关问题。 用户的问题是关于TreeMap的“函数接口”,可能需要明确的是,TreeMap本身是Java中的一个类,属于java.util包,实现了NavigableMap接口,基于红黑树实现。而“函数接口”在Java中通常指的是只有一个抽象方法的接口,比如Comparator或Runnable。这里用户可能指的是TreeMap的构造函数中涉及到的Comparator接口,或者是与Lambda表达式结合使用的函数式接口。 接下来,我需要回顾TreeMap的主要构造函数和相关方法。TreeMap的构造函数包括默认构造函数、接受Comparator的构造函数,以及从其他Map初始化的构造函数。其中,Comparator用于自定义排序规则,而Comparator是一个函数式接口,可以用Lambda表达式实现。 用户可能对如何在TreeMap中使用自定义排序感兴趣,或者想了解如何通过传递Comparator来改变键的顺序。此外,TreeMap的put、get等方法也是关键点,但用户的问题更侧重于接口部分,所以应重点放在Comparator和NavigableMap接口上。 需要检查是否有其他函数式接口与TreeMap相关,比如在遍历或处理数据时使用的BiConsumer等,但主要的部分还是Comparator。用户可能在实际使用中遇到了排序问题,或者想了解如何自定义排序规则,特别是在处理自定义对象作为键时。 还需要考虑用户可能的误解,比如是否将函数式接口与Map接口中的默认方法混淆,例如replaceAll,它接受BiFunction接口,这也是函数式接口。不过,TreeMap作为Map的实现,可能继承了这些方法,但核心的排序机制还是依赖于Comparator。 最后,需要组织回答的结构,先介绍TreeMap的基本概念,然后详细说明构造函数中涉及的Comparator,再提到其他相关的方法和接口,如NavigableMap提供的方法,以及可能的函数式接口应用场景,比如使用Lambda简化Comparator的实现。确保语言简洁明了,示例清晰,帮助用户理解如何在实际编码中应用这些接口。</think>`TreeMap` 是 Java 中基于红黑树(一种自平衡二叉搜索树)实现的 `NavigableMap` 接口的有序映射类。它的核心特点是**按键的自然顺序(`Comparable`)或自定义比较器(`Comparator`)自动排序**。以下是其关键函数接口和特性: --- ### **1. 构造函数** - **`TreeMap()`** 使用键的自然顺序(要求键实现 `Comparable` 接口)。 ```java TreeMap<String, Integer> map = new TreeMap<>(); ``` - **`TreeMap(Comparator<? super K> comparator)`** 自定义比较器,控制键的排序逻辑。 ```java // 按字符串长度排序 TreeMap<String, Integer> map = new TreeMap<>( (s1, s2) -> Integer.compare(s1.length(), s2.length()) ); ``` - **`TreeMap(Map<? extends K, ? extends V> m)`** 从其他 Map 初始化,按自然顺序排序。 - **`TreeMap(SortedMap<K, ? extends V> m)`** 复制已有 `SortedMap` 的排序规则和键值对。 --- ### **2. 核心方法** - **排序相关** - `Comparator<? super K> comparator()`:返回使用的比较器,自然排序时返回 `null`。 - `K firstKey()` / `K lastKey()`:返回最小/最大键。 - `Map.Entry<K, V> firstEntry()` / `Map.Entry<K, V> lastEntry()`:返回最小/最大键值对。 - **范围查询**(得益于红黑树的有序性) - `SortedMap<K, V> subMap(K fromKey, K toKey)`:返回键在 `[fromKey, toKey)` 的子映射。 - `SortedMap<K, V> headMap(K toKey)`:返回键小于 `toKey` 的子映射。 - `SortedMap<K, V> tailMap(K fromKey)`:返回键大于等于 `fromKey` 的子映射。 - **导航方法**(来自 `NavigableMap` 接口) - `Map.Entry<K, V> lowerEntry(K key)`:返回小于给定键的最大键值对。 - `Map.Entry<K, V> higherEntry(K key)`:返回大于给定键的最小键值对。 - `K floorKey(K key)`:返回小于等于给定键的最大键。 --- ### **3. 函数式接口应用** TreeMap 可以与 Java 函数式接口结合使用,例如: - **自定义 `Comparator`**(函数式接口)实现灵活排序: ```java TreeMap<String, Integer> map = new TreeMap<>( Comparator.comparingInt(String::length).reversed() ); ``` - **遍历操作**结合 `BiConsumer`(函数式接口): ```java map.forEach((key, value) -> System.out.println(key + ": " + value)); ``` --- ### **4. 示例代码** ```java TreeMap<Integer, String> map = new TreeMap<>(); map.put(3, "Apple"); map.put(1, "Banana"); map.put(2, "Cherry"); // 输出按键排序:{1=Banana, 2=Cherry, 3=Apple} System.out.println(map); // 获取第一个键(最小键) System.out.println(map.firstKey()); // 输出 1 // 获取键小于 3 的子映射 System.out.println(map.headMap(3)); // 输出 {1=Banana, 2=Cherry} ``` --- ### **关键特性** - **时间复杂度**:`put`、`get`、`remove` 等操作的时间复杂度为 `O(log n)`。 - **线程不安全**:需手动同步或使用 `Collections.synchronizedSortedMap` 包装。 - **允许 `null` 值**,但若使用自然排序,键不能为 `null`(依赖 `Comparable` 会抛 `NullPointerException`)。 通过 `Comparator` 和 `NavigableMap` 接口,`TreeMap` 提供了高度灵活的有序键值管理能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值