Java 实现我自己的Collections.binarySearch方法

Java 实现我自己的Collections.binarySearch方法,java,arrays,Java,Arrays,目前,我正在自学java,并在我的教科书中做一个练习,它要求我在一个文本文件中输入1000个姓名和相应的电话号码,并基本上询问用户想要搜索什么 我的代码现在所做的是使用Collections.binarySearch查找电话号码或姓名。然而,我想知道如何实现我自己的二进制搜索,因为本章基本上是对搜索和排序的介绍,所以我想我自己会学到更多 以下是我的代码的重要部分 这里我使用了可比较的界面 public int compareTo(Item otherObject) { Item

目前,我正在自学java,并在我的教科书中做一个练习,它要求我在一个文本文件中输入1000个姓名和相应的电话号码,并基本上询问用户想要搜索什么

我的代码现在所做的是使用
Collections.binarySearch
查找电话号码或姓名。然而,我想知道如何实现我自己的二进制搜索,因为本章基本上是对搜索和排序的介绍,所以我想我自己会学到更多

以下是我的代码的重要部分

这里我使用了
可比较的
界面

public int compareTo(Item otherObject)
   {
      Item other = (Item) otherObject;
      return key.compareTo(other.key);
   }
然后,我通过将电话号码和姓名添加到ArrayList中

 // Read a line containing the name
       String name = in.nextLine();
         // Read a line containing the number
       String number = in.nextLine();
         // Store the name and number in the byName array list
         byName.add(new Item(name, number));
         // Store the number and name in the byNumber array list
         byNumber.add(new Item(number, name));
然后调用另一个

int index = Collections.binarySearch(byName, new Item(k,""));
   if(index<0) return null;
   return byName.get(index).getValue();
然而,我不确定这是否是正确的方法。鉴于arraylist中有一堆需要排序的对象,而不是一个简单的数组,有没有人能指导我如何准确地格式化二进制搜索的方法

当前工作代码

下面是我目前使用的使用集合的工作方法的完整代码。binarySearch

/Item.java:

/**
   An item with a key and a value.
*/
public class Item implements Comparable<Item>
{
   private String key;
   private String value;
   /**
      Constructs an Item object.
      @param k the key string
      @param v the value of the item
   */
   public Item(String k, String v)
   {
      key = k;
      value = v;
   }
   /**
      Gets the key.
      @return the key
   */
   public String getKey()
   {
      return key;
   }
   /**
      Gets the value.
      @return the value
   */
   public String getValue()
   {
      return value;
   }
   public int compareTo(Item otherObject)
   {
      Item other = (Item) otherObject;
      return key.compareTo(other.key);
   }
}

//LookupTable.java:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
/**
   A table for lookups and reverse lookups
*/
public class LookupTable
{
   private ArrayList<Item> byName;
   private ArrayList<Item> byNumber;
   /**
      Constructs a LookupTable object.
   */
   public LookupTable()
   {
      byName = new ArrayList<Item>();
      byNumber = new ArrayList<Item>();
   }
   /**
      Reads name and number pairs from the Scanner
      and adds them to the byName and byNumber array lists.
      @param in the scanner for reading the input
   */
   public void read(Scanner in)
   {
      while (in.hasNextLine())
      {
         // Read a line containing the name
       String name = in.nextLine();
         // Read a line containing the number
       String number = in.nextLine();
         // Store the name and number in the byName array list
         byName.add(new Item(name, number));
         // Store the number and name in the byNumber array list
         byNumber.add(new Item(number, name));
      }
      // Sort the byName Items so we can binary search
      Collections.sort(byName);
      // Sort the byNumber Items so we can binary search
      Collections.sort(byNumber);
   }
   /**
      Looks up an item in the table.
      @param k the key to find
      @return the value with the given key, or null if no
      such item was found.
   */
   public String lookup(String k)
   {
      // Use the Collections.binarySearch() method to find the
      // position of the matching name in the byName array list.
      // Return null if position is less than 0 (not found).
      // Otherwise, return the number for the found name.
     int index = Collections.binarySearch(byName, new Item(k,""));
   if(index<0) return null;
   return byName.get(index).getValue();
   }
   /**
      Looks up an item in the table.
      @param v the value to find
      @return the key with the given value, or null if no
      such item was found.
   */
   public String reverseLookup(String v)
   {
      // Use the Collections.binarySearch() method to find the
      // position of the matching number in the byNumber array list.
      // Return null if position is less than 0 (not found).
      // Otherwise, return the name for the found number.
     int index = Collections.binarySearch(byNumber, new Item(v, ""));
   if(index<0) return null;
   return byNumber.get(index).getValue();
   }
}

//PhoneLookup.java:

import java.io.IOException;
import java.io.FileReader;
import java.util.Scanner;
/* The input file has the format
Abbott, Amy
408-924-1669
Abeyta, Ric
408-924-2185
Abrams, Arthur
408-924-6120
Abriam-Yago, Kathy
408-924-3159
Accardo, Dan
408-924-2236
Acevedo, Elvira
408-924-5200
Acevedo, Gloria
408-924-6556
Achtenhagen, Stephen
408-924-3522
. . .
*/
public class PhoneLookup
{
   public static void main(String[] args) throws IOException
   {
      Scanner in = new Scanner(System.in);
      System.out.println("Enter the name of the phonebook file: ");
      String fileName = in.nextLine();
      LookupTable table = new LookupTable();
      FileReader reader = new FileReader(fileName);
      table.read(new Scanner(reader));
      boolean more = true;
      while (more)
      {
         System.out.println("Lookup N)ame, P)hone number, Q)uit?");
         String cmd = in.nextLine();
         if (cmd.equalsIgnoreCase("Q"))
            more = false;
         else if (cmd.equalsIgnoreCase("N"))
         {
            System.out.println("Enter name:");
            String n = in.nextLine();
            System.out.println("Phone number: " + table.lookup(n));
         }
         else if (cmd.equalsIgnoreCase("P"))
         {
            System.out.println("Enter phone number:");
            String n = in.nextLine();
            System.out.println("Name: " + table.reverseLookup(n));
         }
      }
   }
}
/Item.java:
/**
带有键和值的项。
*/
公共类项实现了可比性
{
私钥;
私有字符串值;
/**
构造一个Item对象。
@参数k键字符串
@param v项目的值
*/
公共项(字符串k、字符串v)
{
key=k;
值=v;
}
/**
拿到钥匙。
@归还钥匙
*/
公共字符串getKey()
{
返回键;
}
/**
获取值。
@返回值
*/
公共字符串getValue()
{
返回值;
}
公共整数比较(项其他对象)
{
项目其他=(项目)其他对象;
返回key.compareTo(其他.key);
}
}
//LookupTable.java:
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Scanner;
/**
用于查找和反向查找的表
*/
公共类可查找
{
私有ArrayList别名;
私有ArrayList byNumber;
/**
构造一个可查找的对象。
*/
公共可查找()
{
byName=新的ArrayList();
byNumber=新的ArrayList();
}
/**
从扫描仪读取名称和数字对
并将它们添加到byName和byNumber数组列表中。
@扫描仪中用于读取输入的参数
*/
公共无效读取(扫描仪输入)
{
while(在.hasNextLine()中)
{
//读取包含名称的行
字符串名称=in.nextLine();
//读包含数字的一行
字符串编号=in.nextLine();
//将名称和编号存储在byName数组列表中
添加(新项目(名称、编号));
//将数字和名称存储在byNumber数组列表中
添加(新项目(编号、名称));
}
//对按名称项进行排序,以便进行二进制搜索
Collections.sort(按名称);
//按编号对项目进行排序,以便进行二进制搜索
集合。排序(按编号);
}
/**
在表中查找项目。
@参数k是要查找的密钥
@返回具有给定键的值,如果没有,则返回null
发现了这样的物品。
*/
公共字符串查找(字符串k)
{
//使用Collections.binarySearch()方法查找
//匹配名称在byName数组列表中的位置。
//如果位置小于0(未找到),则返回null。
//否则,返回找到的名称的编号。
int index=Collections.binarySearch(按名称,新项(k,”);

if(index您可以从JDK源代码中找到JDK是如何做到这一点的。在
java.util.Collections

private static <T>
    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
私有静态

int indexedBinarySearch(List二进制搜索是一种非常简单的算法。在伪代码中,它是:

find(list, item):
    if list is empty
        return not found
    get middle item from list
    if item matches middle
        return middle
    else if item is before middle
        return find(list before middle, item)
    else
        return find(list after middle, item)
必须对列表进行排序才能使其正常工作。您可以使用
list.subList
来避免复制或传递索引


在您的情况下,您希望能够按多个条件进行搜索。如果您将一个参数传递到您的方法中,该参数定义了您要搜索的内容,则最有意义。

我强烈建议您编写一个简单的[mvce]演示您遇到的问题。没有人会涉过这堵代码墙,其中大部分与问题无关。请访问并阅读。您是否要求他人为您提供进行二进制搜索的代码?看起来是这样。如果您有特定问题,请具体说明,但看起来您没有合作还没有做二进制搜索,所以最好先从那里开始。
find(list, item):
    if list is empty
        return not found
    get middle item from list
    if item matches middle
        return middle
    else if item is before middle
        return find(list before middle, item)
    else
        return find(list after middle, item)