如何按属性查询内存对象?

时间:2016-02-11 15:23:08

标签: java

我正在获取300个json个对象的列表,这些对象将在内存中缓存一天。在执行应用程序期间,我想通过其属性查询对象。

示例:

@XmlRootElement(name = "persons")
@XmlAccessorType(XmlAccessType.FIELD)
class PersonsDTO {
    private List<PersonDTO> persons;

    public static class PersonDTO {
        private String name;
        private int age;
        //lots of more attributes
        private Address address;
    }
}

在这里,我想运行类似于数据库的查询,例如:

findByname("john doe");
findByAgeBetween(10, 18);

问题:我怎样才能最好地为那些“查询”查找准备数据?为每个查询函数创建一个HashMap,然后我可以返回预先计算的结果?

或者是否有任何类似数据库的内存系统我可以使用并且可以查询类似于真实的数据库?

5 个答案:

答案 0 :(得分:3)

您可以使用基于SQL的内存数据库,例如DerbyHSQLDB。 您可以在内存数据库中使用NoSQL,例如hazelcastMapDB。 您可以使用支持EHCache等查询的缓存解决方案。

但300件物品很小。您可以循环遍历它们并在数组中使用它们,并且如果您确实需要(仅在其上执行大量查询),则仅添加基于Map的索引。

这一切都归结为:

  1. 您多久会查询一次此数据集?
  2. 查询是否已修复(我想要Joe Blake),带参数的固定查询(我希望每个人都叫X)还是自由格式?
  3. 如果您很少查询数据集并且使用参数修复/修复查询,那么我只是遍历数据集(Java 8 Streams API;最简单的解决方案)。 如果你需要经常使用固定查询来点击数据集,那么我就预先计算结果。 如果您需要使用带参数的少量固定查询来大量访问数据集,并考虑添加一些自制make索引(哈希映射)。 如果您需要自由格式查询,我会考虑使用内存数据库(NoSQL或SQL)或Java 8 Streams API。

答案 1 :(得分:3)

除非你有特定的性能要求,否则我会强制它。扫描300个条目的时间应少于0.1毫秒。

这将允许您使用内置的流API。

private List<PersonDTO> persons;

public List<PersonDTO> findBy(Predicate<PersionDTO> test) {
    return persons.stream().filter(test).collect(Collectors.toList());
}


// findByName
List<PersonDTO> david = findBy(p -> p.getName().startsWith("David "));

// find by age
List<PersonDTO> youngAdult= findBy(p -> p.getAge() >= 18 && p.getAge() <= 30);

答案 2 :(得分:2)

HSQLDB是一个用Java编写的内存中SQL数据库。

否则您将需要设计和构建自己的引擎。您可能有专门的方法名称,如您所示,并且避免了一些查询解析方面,但您仍然需要自己实现查询,包括定义匹配(精确,部分,区分大小写等)。

答案 3 :(得分:1)

300并不是一个很大的数字(虽然斯巴达人和波斯人可能会争论......)。

  1. 因此,在一个简单的解决方案中,您可以将对象保存在列表中,只需遍历列表并使用所需属性对对象进行峰值处理。这是非常低效的,但对于300它将工作得很好。

    1. 如果您使用Java 8,可以使用并行进行一些升级 流式传输和过滤,可以利用您的处理器资源 以最好的方式。仍然不是非常有效率。

    2. 另一个想法 - 为每个对象添加或生成唯一ID,并创建mater地图 你的身份证件给你的DTO。然后为每个创建单独的地图 您打算搜索的属性。每张地图都应该拥有财产 值为具有该值的DTO的ID列表。然后你查询 您的属性地图以查找ID,然后搜索您的主地图 找到DTO。一般来说,这是一种经典的权衡 表现和空间。

答案 4 :(得分:1)

在Java8中,您可以使用流来完成这个简单的任务。当然,您需要评估它是否足以满足您的需要,但这是一种非常快速而简单的实现方式,无需设置本地数据库。

public List<PersonDTO> findByAgeBetween(min, max){
    List<PersonDTO> byAge = 
      personList.stream().
      filter(p -> p.age >= min).
      filter(p -> p.age <= max).
      collect(Collectors.toList());
    return byAge;
}

与其他查询类似