实现我自己的Collections.binarySearch方法

时间:2016-10-10 01:38:33

标签: java arrays

目前我正在自学java,并且正在我的教科书中练习,它要求我在一个带有相应电话号码的文本文件中取1000个名字,并且基本上询问用户他们想要搜索的内容。

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

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

我在这里使用comparable界面

public int compareTo(Item otherObject)
   {
      Item other = (Item) otherObject;
      return key.compareTo(other.key);
   }

然后我通过

将电话号码和姓名添加到ArrayLists中
 // 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();

我还有另一种可以搜索byPhone

的方法

因此正确地找到了一切。

我的问题

我想知道的是如何实现我自己的方法,它将执行binarySearch。我已经完成了对数组进行二进制搜索并在数组中查找数字,但由于我们正在处理对象和数组列表,因此我很难理解如何设置该方法。

例如,我想制作一个这样的方法:

int myBinarySearch(ArrayList<Item> thisItem, Object Item)
    {
            // search logic here
    }

但我不确定这是否是正确的做法。有人可以指导我如何格式化我的二进制搜索方法,因为我在arraylist中有一堆对象需要排序,而不是一个简单的数组。

当前正在运行的代码

以下是使用Collections.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));
         }
      }
   }
}

2 个答案:

答案 0 :(得分:1)

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

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

与您正在工作的人非常相似。

答案 1 :(得分:0)

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

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来避免复制或传递索引。

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