java 为什么Collections.binarySearch(List< ?extends T> list,T key,Comparator< ?super T> c)方法是否需要一个Comparator对象作为它的参数?

rm5edbpk  于 2023-10-14  发布在  Java
关注(0)|答案(3)|浏览(95)

下面是我的代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class MyComp implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
    
}
public class CollectionsAlgo2 {

    public static void main(String[] args) {
        // Create an ArrayList
        ArrayList<String> al = new ArrayList<>();
        
        // Add elements to the array list.
        al.add("C");
        al.add("A");
        al.add("E");
        al.add("B");
        al.add("D");
        al.add("F");
        al.add(1, "A2");
        
        System.out.println("al: "+al);
        Collections.sort(al);
        System.out.println("al after sorting: "+al);
        int pos = Collections.binarySearch(al, "B", new MyComp());
        System.out.println("pos: "+pos);

    }

}

我的问题是在Collections.binarySearch(List<?extends T> list,T key,Comparator<?super T> c),因为我们已经按升序传递了列表?
这个比较器参考如何帮助进行二分搜索?

xpcnnkqh

xpcnnkqh1#

基本上,二分查找算法需要知道如何比较元素。当它检查一个平分点时,它需要知道你要搜索的元素是在左边还是右边。这需要一个比较。
Collections有两个binarySearch方法,一个有比较器,一个没有。如果你的元素是Comparable,那么你不需要传递一个比较器。你可以只传递列表和搜索键:

int binarySearch​(List<? extends Comparable<? super T>> list, T key)

如果它们不是Comparable,那么你需要告诉binarySearch如何通过传递一个自定义的Comparator来比较它们:

int binarySearch​(List<? extends T> list, T key, Comparator<? super T> c)

在示例代码中,StringComparable,因此不需要MyComp

int pos = Collections.binarySearch(al, "B");
41zrol4v

41zrol4v2#

请记住,Java的数组类中有许多不同的方法可以使用二进制搜索。你可以找到一个here的列表。
一般来说,如果你在数组或列表中搜索一个原语、字节或类似的对象,你应该使用一个不包含任何比较器的方法。
但是,如果您有一个默认情况下不可比较的对象列表,该怎么办?例如,假设您定义了一个Person数据类型,它具有一些属性,如身高、年龄和名称。现在,假设您正在存储一个人员列表。如果你想在Person对象的排序列表中找到某个Person,默认情况下,Java不知道如何执行这种二分搜索。
需要提醒的是,Java通过比较当前检查的键和目标键来确定在二进制搜索中移动的位置。但是,Java不知道检查一个Person对象是否大于、小于或等于另一个对象意味着什么。它是否应该使用高度来确定哪个更大?是否应该根据姓氏或其他变量进行比较?
这就是比较器的用武之地。我需要告诉Java,当我请求比较两个Person对象时,这意味着什么。
要编写比较器,您需要创建一个类。这可以是与对象在同一文件中的私有类,或者您甚至可以将其写入方法本身。比较器应采用两种方法:compareequals。您可以查看文档here。一旦你写了这个,你就传入了你刚刚创建的比较器,所以Java现在知道如何比较给定列表或数组中的对象。

c0vxltue

c0vxltue3#

有两组sort()和binarySearch()。它们必须匹配,因为binarySearch()必须接受一个按升序排序的列表。

public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)

方法需要T extends Comparable<?你正在使用Comparable的实现进行排序和搜索。不需要设置比较器。
Javadoc for binarySearch:
在进行此调用之前,列表必须根据其元素的自然顺序(如通过**sort(List)**方法)按升序排序。

public static <T> void sort(List<T> list, Comparator<? super T> c)
public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)

所有方法都不需要T extends Comparable<?super T>。即使你已经实现了Comparable,你现在也可以选择作为一个不同的Comparator来排序和搜索。
Javadoc for binarySearch:
在进行此调用之前,必须根据指定的比较器(如通过**sort(List,Comparator)**方法)将列表按升序排序。

record Person(String name, String address) implements Comparable<Person>{

    @Override
    public int compareTo(Person o) {
        return this.name.compareTo(o.name);
    }
}
public class binary_sorted_object {

    public static void main(String[] args) {
        List<Person> t = new ArrayList<>(List.of(
                new Person("a", "400 Line"),
                new Person("c", "100 Line"),
                new Person("b", "800 Line")));

        Collections.sort(t);
        //sorted into ascending order according to the natural ordering of its elements (as by the sort(List) method)
        System.out.println(Collections.binarySearch(t, new Person("a", "400 Line")));

        Collections.sort(t, Comparator.comparing(Person::address));
        //Sorts the specified list according to the order induced by the specified comparator
        System.out.println(Collections.binarySearch(t,  new Person("a", "400 Line"), Comparator.comparing(Person::address)));
    }
}

相关问题