【问题标题】:Sorting and Filtering List of Objects排序和过滤对象列表
【发布时间】:2019-03-31 23:26:58
【问题描述】:

我有一个外部服务,我可以从中获取组织的所有员工详细信息,如下所示。我正在使用 java8 和 spring cloud feign 客户端来使用服务

[
  {
    "employee": {
      "empId": "empId123",
      "name": "Emp1",
      "houseNumber": "5",
      "firstName": "firstName1",
      "lastName": "lastName1",
      "city": "city1",
      "band": "A"
    },
    "type": "ABC"
  },
  {
    "employee": {
      "empId": "empId456",
      "name": "Emp2",
      "houseNumber": "7",
      "firstName": "firstName2",
      "lastName": "lastName2",
      "city": "city2",
      "band": "B"
    },
    "type": "ABC"
  }
  :
  :
]

员工详细信息服务有大约 10000+ 员工详细信息。

我需要创建另外两个服务

  1. 根据cityhouseNumber排序并返回所有员工
  2. 根据citybandempId等特定属性过滤员工的服务。

目前我正在使用的排序服务如下所示

final List<Employees> employeesList = employeeService.getAllEmployees().stream()
                .sorted((emp1, emp2) -> p1.getAddress().getCity().compareTo(emp2.getAddress().getCity()))
                .sorted((emp1, emp2) -> p1.getAddress().getHouseNumber().compareTo(emp2.getAddress().getHouseNumber()))
                .collect(Collectors.toList());

为了过滤,我使用下面的代码

String cityName = "some city name"...

final List<Employees> employeesfilteredList = employeeService.getAllEmployees()
    .stream()
    .filter(employee -> employee.getAddress().getCity().equalsIgnoreCase(cityName == null ? "" : cityName))
    .collect(Collectors.toList());

但是我的技术人员客户说这有性能问题,并要求带来一些时间复杂度较低的东西(最好是 O(1))来带来结果

谁能告诉我我正在使用的当前方法有什么问题,有什么方法可以让我以任何其他方式或方法即兴发挥它

【问题讨论】:

  • 1.您的排序是错误的:它按城市排序,然后再按门牌号对所有元素进行排序。 2. 没有办法在 O(1) 中对列表进行排序或过滤。排序是 O(n*log(n)),过滤是 O(n)。最好的方法是让外部服务通过将该任务委托给其数据库来执行此过滤和排序,而不是将所有内容加载到内存中,通过网络发送所有内容,反序列化所有内容,然后过滤掉其中的大部分内容。
  • 认真的吗?门牌号优先于城市?那么街道呢?除此之外,您可以避免多次排序,可以避免在每个谓词评估中执行冗余的null 检查,但不能更改时间复杂度。线性列表是线性列表。当底层服务没有提供更好的东西时,你无法改变它。哦,Employees 对于一个为每个实例建模一个员工的类来说是一个坏名字......
  • 感谢 JBNizetHolget 的回复。只是一个想法不确定我是否正确,如何在哈希表下维护它在插入、搜索和删除中的 O(1) (i.stack.imgur.com/l56sp.png)
  • @AlexMan 您主要关注获取、插入和删除的时间复杂性。虽然你打算在你的服务中做的是排序、过滤等。但是有区别。
  • 如果你有能力调用外部系统一次,然后将结果存储在 HashMap 中,并将该 HashMap 用于所有后续请求,而无需从外部系统获取新值,那么不要使用哈希映射。使用具有适当索引的数据库,并使用它来过滤和排序结果。

标签: java sorting collections java-8 time-complexity


【解决方案1】:

我能想到的你当然可以即兴发挥的一件事是对sorted 的两次调用,只能调用一次:

// replacing with 'employees' for 'employeeService.getAllEmployees()'
Comparator<Employees> compareBasedOnCity = 
            Comparator.comparing(emp -> emp.getAddress().getCity());
Comparator<Employees> compareBasedOnHouse = 
            Comparator.comparing(emp -> emp.getAddress().getHouseNumber());
employees.sort(compareBasedOnCity.thenComparing(compareBasedOnHouse));

另一个在过滤期间是避免将null""字符串视为相同:

List<Employees> finalList = employees.stream()
            .filter(employee -> employee.getAddress().getCity().equalsIgnoreCase(cityName))
            // don't consider empty city name same as null (think of "  " otherwise)
            .collect(Collectors.toList());

但是,正如 HolgerJB Nizet 已经指出的那样,这一切都不会像您期望的那样将复杂性从 O(nlogn) 降低到 O(1)

进一步将其与访问、插入和删除等操作进行比较也不等同。由于执行的操作也不同。

【讨论】:

  • ...和 ​​if 您想将null 搜索字符串视为"",您只需要在流操作之前执行一次,@987654332 @
  • @nullpointer 感谢您的回复....出于好奇,您能告诉我这种employees.sort(compareBasedOnCity.thenComparing(compareBasedOnHouse)); 的性能如何比我用过的更好....
  • @AlexMan 第二个比较器只查询第一个比较器认为相等的元素对。相反,两次排序操作总是两次排序操作。在最坏的情况下,整个第一个排序操作都已过时。
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
相关资源
最近更新 更多