代码之家  ›  专栏  ›  技术社区  ›  Adam Outler

在Java表中,我用什么来执行类似SQL的查找?

  •  0
  • Adam Outler  · 技术社区  · 14 年前

    我有一个二维阵列

    public static class Status{
    public static String[][] Data= {
    { "FriendlyName","Value","Units","Serial","Min","Max","Mode","TestID","notes" },
    { "PIDs supported [01 – 20]:",null,"Binary","0",null,null,"1","0",null },
    { "Online Monitors since DTCs cleared:",null,"Binary","1",null,null,"1","1",null },
    { "Freeze DTC:",null,"NONE IN MODE 1","2",null,null,"1","2",null },
    

    我想

    SELECT "FriendlyName","Value" FROM Data WHERE "Mode" = "1" and "TestID" = "2"
    

    我该怎么做?最快的执行时间很重要,因为每分钟可能有数百个这样的执行时间。

    5 回复  |  直到 14 年前
        1
  •  1
  •   Carl Manaster    14 年前

    想想它需要多一般。对于像SQL这样真正普通的问题,解决方案看起来可能与一些非常具体的查询的解决方案不太一样。

    在您展示它时,我倾向于避免使用二维字符串数组,而是创建一个集合——可能是一个数组列表,但是如果您经常进行插入和删除,那么LinkedList可能更适合某种结构类。所以

     List<MyThing> list = new ArrayList<MyThing>();
    

    并使用哈希图为要搜索的字段编制索引:

     Map<Integer, MyThing> modeIndex = new HashMap<Integer, MyThing>()
     for (MyThing thing : list)
         modeIndex.put(thing.mode, thing);
    

    把它写下来让我意识到这本身是不可能的,因为多个事物可能有相同的模式。所以可能是一个多映射——或者通过使映射的值类型不是虚构的,而是列表来滚动自己的值。 Google Collections 有一个很好的多映射实现。

        2
  •  0
  •   Stephen C    14 年前

    这并不能确切地回答你的问题,但是可以用JAVM内存中的所有表运行一些Java RDBMS。例如, HSQLDB . 这将为您提供SQL选择的全部功能,而无需磁盘访问开销。唯一的问题是,你不能像你所问的那样查询原始的Java数据结构。您首先必须将数据插入数据库的内存表中。

    (我没试过这个……也许有人会评论这种方法是否真的可行。)

        3
  •  0
  •   BalusC    14 年前

    至于你的实际情况 问题 ,在C中,他们曾经使用 LINQ (语言集成查询),这得益于语言对 closures . 现在Java 6作为最新的官方版本,Java不支持闭包,但它将 come 在即将到来的Java 7中。基于LINQ的基于Java 7的等价物很可能是 JaQue .

    至于你的实际情况 问题 ,您肯定使用了错误的数据结构。您的最佳选择是转换 String[][] 变成一个 List<Entity> 使用方便的搜索/过滤API Guava 如Carl Manaster所建议。这个 Iterables#filter() 会是个好的开始。

        4
  •  0
  •   Enno Shioji    14 年前

    编辑:我看了你的数组,我认为这绝对是RDBMS的工作。如果您想要像功能(快速/不需要数据库服务器)这样的内存数据结构,嵌入在像hsqldb这样的内存数据库中,h2可以提供这些功能。

    如果您想要好的执行时间,您必须有一个好的数据结构。如果您只是无序地将数据存储在一个二维数组中,那么您将主要被困在O(N)中。

    例如,您需要索引,就像其他RDBMS一样。例如,如果你经常使用 WHERE 像这样的条款 WHERE name='Brian' AND last_name='Smith' 您可以这样做(类似于伪代码):

    Set<Entry> everyEntry = //the set that contains all data
    Map<String, Set<Entry>> indexedSet = newMap();
    for(String name : unionSetOfNames){
        Set<Entry> subset = Iterables.collect(new HasName(name), everyEntries);
        indexedSet.put(name, subset);
    }
    //and later...
    Set<Entry> brians = indexedSet.get("Brian");
    Entry target = Iterables.find(new HasLastName("Smith"),brians);
    

    (如果示例代码中的guava api用法错误(它是伪代码),请原谅我!但是你明白了)。

    在上面的代码中,您将进行一次O(1)的查找,然后进行另一次O(n)的查找,但要在更小的子集上进行。因此,这比对整个集合进行O(N)查找等更有效。如果使用的是按 last_name 并使用二进制搜索,该查找将变为O(log n)。像这样的事情。外面有很多数据结构,这只是一个非常简单的例子。

    因此,最后,如果我是您,我将定义自己的类,并使用JDK中可用的一些标准数据结构创建数据结构。如果这还不够,我可能会看一些其他的数据结构,但是如果它变得非常复杂,我想我只需要使用一些内存中的RDBM,比如hsqldb或h2。它们很容易嵌入,因此您的内存数据结构非常接近。随着越来越多的人做复杂的事情,这种选择很可能会提供更好的性能。

    还请注意,我使用了 Google Guava 我的示例代码中的库..它们非常好,我强烈推荐使用它们,因为这样更好。当然,也不要忘记查看java.utli.collections包。

        5
  •  0
  •   Adam Outler    14 年前

    最后我使用了一个查找表。90%的数据是从接近顶部的位置引用的。

        public static int lookupReferenceInTable (String instanceMode, String instanceTID){
            int ModeMatches[]=getReferencesToMode(Integer.parseInt(instanceMode));
            int lineLookup = getReferenceFromPossibleMatches(ModeMatches, instanceTID);
            return lineLookup;
        }
    
    
    
            private static int getReferenceFromPossibleMatches(int[] ModeMatches, String instanceTID) {
          int counter = 0;
          int match = 0;
          instanceTID=instanceTID.trim();
          while ( counter < ModeMatches.length ){
             int x = ModeMatches[counter];
             if (Data[x][DataTestID].equals(instanceTID)){
             return ModeMatches[counter];
             }
             counter ++ ;
          }
          return match;
    
        }
    

    它可以进一步优化,这样它就不会在所有数组中循环,而是在列上循环,直到找到匹配项,然后循环下一个,然后循环下一个。数据以流动且组织良好的方式进行布局,因此基于3个条件的查找只需进行与行等量的检查。