简体   繁体   English

为什么 is.binary 搜索返回随机负值,即使它以前有效

[英]Why is .binary search returning random negative values even though it worked before

I've been writing this program that reads in from a text file consisting of names and phone numbers.我一直在编写这个程序,它从一个包含姓名和电话号码的文本文件中读入。 I created 2 arraylists both containing Item objects.我创建了 2 个数组列表,它们都包含 Item 对象。 names array list contains Item object haveing names as the key value and phone numbers as the value value.名称数组列表包含项目 object,名称作为键值,电话号码作为值。 While the numbers array list is the opposite having the key value being phone numbers and the value value names.而数字数组列表则相反,键值是电话号码,值是名称。

Here is the code:这是代码:

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.io.FileNotFoundException;

public class Test 
{
    
public static void main(String[] args) throws FileNotFoundException
{
    File inputFile = new File("directory.txt");
    ArrayList<Item> names = new ArrayList<Item>();
    ArrayList<Item> numbers = new ArrayList<Item>();
    
    Scanner in1 = new Scanner(inputFile);
    while(in1.hasNextLine())
    {
        String name = in1.nextLine();
        String num = in1.nextLine();
        Item item = new Item(name , num);
        names.add(item);
    }
    
    Scanner in2 = new Scanner(inputFile);
    while(in2.hasNextLine())
    {
        String name = in2.nextLine();
        String num = in2.nextLine();
        Item item = new Item(num, name);
        numbers.add(item);
    }
    
    Collections.sort(names);
    Collections.sort(numbers);
    
    Scanner in = new Scanner(System.in);
    
    System.out.println("Enter number: ");
    String num = in.next();
    int index = Collections.binarySearch(numbers, new Item(num, null));
    System.out.println(index);
    System.out.println(numbers.get(index).getValue()); 
    
    System.out.println("Enter name: ");
    num = in.next();
    index = Collections.binarySearch(names, new Item(num, null));
    System.out.println(index);
    System.out.println(names.get(index).getValue());
        

}

}


public class Item implements Comparable<Item>
{
  
   public Item(String k, String v)
   { 
      key = k;
      value = v;
   }
   
   
   public String getKey()
   { 
      return key;
   }
   
   
   public String getValue()
   { 
      return value;
   }

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

   private String key;
   private String value;
}

When testing entering the phone number it outputs the correct name and since it.binarysearch got the correct index but when entering a name outputs a random negative index value and I have no clue why.在测试输入电话号码时,它会输出正确的名称,因为 it.binarysearch 得到了正确的索引,但是在输入名称时会输出一个随机的负索引值,我不知道为什么。 [Here is how the console looks like][1] [1]: https://i.stack.imgur.com/rrVEk.png [这是控制台的样子][1] [1]:https://i.stack.imgur.com/rrVEk.png

Sorry if this post is not so good.对不起,如果这篇文章不是很好。 This is my first post and I really need help.这是我的第一篇文章,我真的需要帮助。 Can't figure this out想不通

In the part where you enter a number, you then search by a number.在输入数字的部分,您可以按数字搜索。

In the second part where you enter a name, you search for a number.在输入名称的第二部分中,您搜索一个数字。 That will not find a name.那将找不到名字。

Your Item class only compares numbers (you call them key and value rather than number and name, it will be clearer if you fix that).你的Item class 只比较数字(你称它们为keyvalue而不是数字和名称,如果你修复它会更清楚)。 You might want two classes (eg NumberItem and NameItem ), one which compares by number, the other which compares by name (make them inherit from Item , which doesn't implement Comparable ).您可能需要两个类(例如NumberItemNameItem ),一个按数字比较,另一个按名称比较(使它们继承自Item ,它不实现Comparable )。

Another strategy is to use the existing tools, and store each type of Item in a Map , one indexed by number, the other by name.另一种策略是使用现有工具,并将每种类型的Item存储在Map中,一个按编号索引,另一个按名称索引。 The internal implementation will probably be more efficient than what you come up with.内部实施可能比您提出的更有效。

By using IntelliJ and a debugger I was able to discover the issue:通过使用 IntelliJ 和调试器,我能够发现问题:

num = in.next();

If you debug right after and you look at num value, you will see it will be: Smith,如果您在之后立即进行调试并查看num值,您会看到它将是: Smith,

Seems that the whitespace is the problem here似乎空格是这里的问题

Let's find out why:让我们找出原因:

If we take a look at Scanner.next() documentation:如果我们看一下Scanner.next()文档:

Finds and returns the next complete token from this scanner.从该扫描器中查找并返回下一个完整的标记。 A complete token is preceded and followed by input that matches the delimiter pattern.一个完整的令牌之前和之后是与定界符模式匹配的输入。 This method may block while waiting for input to scan, even if a previous invocation of hasNext returned true.此方法可能会在等待输入扫描时阻塞,即使先前调用 hasNext 返回 true 也是如此。

This means that the scanner will take only the text until it encounters the delimiter.这意味着扫描器在遇到分隔符之前将只接受文本。 Who is the delimiter?谁是分界线? It should be a default one if you didn't provide it, right?不提供的话应该是默认的吧? Let's take a look again in Scanner class and search for the default delimiter.让我们在 Scanner class 中再次查看并搜索默认分隔符。

Right at the top of the class the documentation states:在 class 的顶部,文档指出:

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace .扫描仪使用分隔符模式将其输入分解为标记,默认情况下匹配空格 The resulting tokens may then be converted into values of different types using the various next methods.然后可以使用各种 next 方法将生成的标记转换为不同类型的值。

So, the whitespace cuts your input from the keyboard.因此,空格会切断您从键盘输入的内容。

Bonus some easy tips & tricks that will help you:附赠一些对您有帮助的简单提示和技巧:

  • Name the variables simple and easy to understand.命名变量简单易懂。 Check out some guides on naming best practices(especially in Java) and naming conventions in Java.在 Java 中查看一些关于命名最佳实践(尤其是在 Java 中)和命名约定的指南。
  • Use the debugger.使用调试器。
  • When your code is not doing what you think it should and you are using "3rd party classes", try to look at what and how are they doing the things under the hood.当您的代码没有按照您认为应该的方式运行并且您正在使用“第 3 方类”时,请尝试查看它们在幕后做了什么以及如何做。 It is enough in most of the cases just to read their documentation(and IDEs like IntelliJ facilitate this by just holding ctrl and pressing click on the method name, it will point you right to the implementation where you can see the method's documentation).在大多数情况下,只需阅读它们的文档就足够了(像 IntelliJ 这样的 IDE 只需按住 ctrl 并单击方法名称,它会直接指向实现,您可以在其中看到方法的文档)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM