Java 如何构造可以在不同键上索引和排序的数据?

Java 如何构造可以在不同键上索引和排序的数据?,java,collections,Java,Collections,我想维护一组具有两个主要属性的数据:1。我可以通过数字ID快速查找对象的存在性,2。我想对数据进行排序,但避免不必要的排序,因为它可能很慢。举一个更具体的例子,我有一组用户数据,其中每个用户都有一个唯一的ID(一个int)和一个唯一的用户名(一个字符串)。我将添加和删除用户,有时我想为用户生成一个可读的、按字母顺序排序的列表,但随着用户数量的增加,排序数据所需的时间也会增加 你将如何构建这个?我能想到的唯一合理的方法是创建两个独立的数据结构,并同时冗余地向这两个结构添加/删除项。随着数据的增长,

我想维护一组具有两个主要属性的数据:1。我可以通过数字ID快速查找对象的存在性,2。我想对数据进行排序,但避免不必要的排序,因为它可能很慢。举一个更具体的例子,我有一组用户数据,其中每个用户都有一个唯一的ID(一个int)和一个唯一的用户名(一个字符串)。我将添加和删除用户,有时我想为用户生成一个可读的、按字母顺序排序的列表,但随着用户数量的增加,排序数据所需的时间也会增加

你将如何构建这个?我能想到的唯一合理的方法是创建两个独立的数据结构,并同时冗余地向这两个结构添加/删除项。随着数据的增长,它将使用比单个结构更多的数据。我还可能以这种方式引入更多的bug,因为我必须提醒自己在稍后返回添加到代码时将操作复制到这两个结构中。换句话说,我可以:

TreeMap<String,Integer> nameSortedMap = new TreeMap<String,Integer>(String.CASE_INSENSITIVE_ORDER);
TreeMap nameSortedMap=newtreemap(String.CASE不区分大小写\u顺序);

Map idMap=newhashmap();
无论何时添加或删除数据,我都会在两个地图上进行。如果我要按ID检索用户名,我会调用idMap.get(ID)或idMap.contains(ID)(查看是否存在用户)。另一方面,如果需要显示排序列表,我将使用nameSortedMap.keySet(),我收集的数据应该已经按名称顺序排列,避免了每次需要排序列表时都需要额外的工作


我的思维过程如何?有没有更好或更简单的方法来实现这一点?谢谢大家!

我可以想到两种方法:

  • 使用数据库并为两列编制索引。数据库速度很快,而且可能非常小(请参见:),但是如果您不需要保存数据,或者如果这是您唯一使用它的目的,那么它们可能会被过度使用
  • 创建一个包含上述两个映射的类,该类处理所有插入和删除操作。这样,您只有一个地方需要记住对这两个对象执行操作。这是我们的主要卖点之一

    • 我可以想到两种方法:

      • 使用数据库并为两列编制索引。数据库速度很快,而且可能非常小(请参见:),但是如果您不需要保存数据,或者如果这是您唯一使用它的目的,那么它们可能会被过度使用
      • 创建一个包含上述两个映射的类,该类处理所有插入和删除操作。这样,您只有一个地方需要记住对这两个对象执行操作。这是我们的主要卖点之一

        • 如果你不经常调用有序列表,我认为没有必要保留两张地图,但如果你愿意这样做的话。我建议您创建一个类来扩展HashMap,并实现处理这两个映射的方法。例如:

          public class UserMap extends HashMap<Integer, String> {
          
              TreeMap<String, Integer> nameSortedMap = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
          
              @Override
              public String put(Integer key, String value) {
                  String put = super.put(key, value);
                  nameSortedMap.put(value, key);
                  return put;
              }
          
              @Override
              public String remove(Object key) {
                  String toRemove = get(key);
                  if (toRemove != null) {
                      remove(key);
                      getOrderedName().remove(toRemove);
                  }
                  return toRemove;
              }
          
              public Set<String> getSortedNames() {
                  return nameSortedMap.keySet();
              }
          
          }
          
          public类UserMap扩展了HashMap{
          TreeMap nameSortedMap=newtreemap(String.CASE不区分大小写\u顺序);
          @凌驾
          公共字符串put(整型键、字符串值){
          字符串put=super.put(键,值);
          nameSortedMap.put(值、键);
          回售;
          }
          @凌驾
          删除公共字符串(对象键){
          字符串toRemove=get(键);
          if(toRemove!=null){
          取下(钥匙);
          getOrderedName().remove(toRemove);
          }
          返乡搬迁;
          }
          公共集getSortedNames(){
          返回nameSortedMap.keySet();
          }
          }
          
          如果您不经常调用有序列表,我认为没有必要保留两个映射,但如果您愿意这样做的话。我建议您创建一个类来扩展HashMap,并实现处理这两个映射的方法。例如:

          public class UserMap extends HashMap<Integer, String> {
          
              TreeMap<String, Integer> nameSortedMap = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
          
              @Override
              public String put(Integer key, String value) {
                  String put = super.put(key, value);
                  nameSortedMap.put(value, key);
                  return put;
              }
          
              @Override
              public String remove(Object key) {
                  String toRemove = get(key);
                  if (toRemove != null) {
                      remove(key);
                      getOrderedName().remove(toRemove);
                  }
                  return toRemove;
              }
          
              public Set<String> getSortedNames() {
                  return nameSortedMap.keySet();
              }
          
          }
          
          public类UserMap扩展了HashMap{
          TreeMap nameSortedMap=newtreemap(String.CASE不区分大小写\u顺序);
          @凌驾
          公共字符串put(整型键、字符串值){
          字符串put=super.put(键,值);
          nameSortedMap.put(值、键);
          回售;
          }
          @凌驾
          删除公共字符串(对象键){
          字符串toRemove=get(键);
          if(toRemove!=null){
          取下(钥匙);
          getOrderedName().remove(toRemove);
          }
          返乡搬迁;
          }
          公共集getSortedNames(){
          返回nameSortedMap.keySet();
          }
          }
          
          @BrendanLong你不认为在数据库中插入/删除的过程比在内存中花费更多吗?@BrendanLong你不认为在数据库中插入/删除的过程比在内存中花费更多吗?