【问题标题】:Searching for a record in a TreeSet on the fly动态搜索 TreeSet 中的记录
【发布时间】:2011-08-29 09:28:59
【问题描述】:

我正在使用 swing 和 awt 库在 Java 中编写一个通讯录应用程序。该应用程序由一个使用 TreeSet 作为 abstractListModel 的 JList 组成。

TreeSet 用于名为 Contact 的类,该类具有私有比较器类,可根据联系人的名字对联系人进行排序。 private boolean equals(Object o) 方法返回 true 如果 Contact 的 mobileNumber 与 O 相同(当然是在转换之后)。

我想在此应用程序中添加搜索功能。我进行了搜索 JTextField 并添加了一个 keyListener ,我想要做的是在按下每个键后,列表会显示一组包含搜索词的缩小结果。在 TreeSet 或任何其他集合中是否有此方法?我希望它类似于您在 iPod 中的音乐应用程序中的内容,例如,当您键入字母“f”时,它会列出所有包含字母 F 的歌曲,但仅在您键入“50 cent”时出现您想要的歌手的歌曲。

感谢您的帮助。

【问题讨论】:

  • 只是为了更清楚。假设我的书中有 4 个联系人:Erich、Erica、Erin 和 Dave。我想要的是: - 当我输入 E 时,列表只显示 Erich、Erica 和 Erin。 - 当我输入 Eric 时,列表只显示 Erich 和 Erica - 当我输入 Erich 时,列表只显示 Erich。基本上,它会在按下每个键时缩小结果范围。
  • 无论怎样解决搜索问题:不要使用 KeyListener(你永远不想在应用程序代码中使用 KeyListener)。这里,合适的观察者服务器是 DocumentListener

标签: java search treeset


【解决方案1】:

如果要查找所有以文本开头的条目(例如“f”),可以使用subSet(from, to) 方法,如下所示:

SortedSet<String> s = new TreeSet<String>(new Comparator<String>() {
  public int compare( String s1, String s2 ) {
    return s1.compareToIgnoreCase( s2 );
  }

});


s.add( "Erich" );
s.add( "Erica" );
s.add( "Erin" );
s.add( "Dave" );
s.add( "Thomas" );

SortedSet<String> result = s.subSet( "e", "e" + Character.MAX_VALUE ); //"e" represents the user input
System.out.println(result);//prints [Erica, Erich, Erin]

result = s.subSet( "Eric", "Eric" + Character.MAX_VALUE );
System.out.println(result); //prints [Erica, Erich]

result = s.subSet( "Erich", "Erich" + Character.MAX_VALUE );
System.out.println(result); //prints [Erich]

由于 tosubset(from, to) 的参数是独占的,因此您需要的东西显然会更大。在我的示例中,我只是添加了Character.MAX_VALUE,但您可能希望获得更好的上限。请注意,这取决于您的比较器,例如它如何处理大小写差异等。

如果您想使用通配符进行过滤,例如所有 包含 文本的文本(例如,f 将转换为 *f*),则无论如何您都必须遍历并检查所有条目.在这种情况下,使用排序集不会获得任何优势。

编辑:将示例更新为您的数据(也添加我 :))。

【讨论】:

  • 效果很好!我担心性能,但它像丝绸一样光滑。非常感谢您的帮助!
  • @Erich 稍微考虑一下“zzzzz”,我建议改用Character.MAX_VALUE。我会更新我的答案。
  • +1。严格来说,排他上界是通过“递增”前缀获得的——例如,以"Eric"开头的字符串的排他上界是"Erid"——但我认为附加Character.MAX_VALUE是正确的方法去。最大字符值不能出现在有效的 UTF-16 中(因为 U+FFFF 是保留的非字符),所以在实践中它不应该出现。
【解决方案2】:

您可以使用java.lang.String 类的boolean startsWith(String prefix) 方法来检查集合中的哪些值是否以输入字符串开头。

例如:

public void getName(Set<String> t, String s)
    {
        for(String str : t) 
        {
            if(str.toLowerCase().startsWith(s.toLowerCase()))
                System.out.println(str);
        }
    }

输入:

Set<String> test = new TreeSet<String>();

        test.add( "Erich" );
        test.add( "Erica" );
        test.add( "Erin" );
        test.add( "Dave" );
        test.add( "Thomas" );

如果你调用方法:

getName(test, "eri");

输出将是:

Erica
Erich
Erin

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2015-09-08
    • 2013-02-15
    • 1970-01-01
    相关资源
    最近更新 更多