在Java中,通过交集后的特定属性对对象列表进行排序

在Java中,通过交集后的特定属性对对象列表进行排序,java,java-8,Java,Java 8,我想我把我要做的事情复杂化了,但是我想要的是根据用户的输入对我的对象列表进行排序。下面是一些背景知识 我有一个模式对象,它有许多字段。用户指定这些值序列化的顺序(如果存在),如下所示: id、dateTime、payload这些值应该存在于架构中。如果没有,我会过滤掉它们。我对用户想要什么和模式喜欢什么执行交集,因此: private List<Field> performIntersection(List<String> subsetFields, List<

我想我把我要做的事情复杂化了,但是我想要的是根据用户的输入对我的对象列表进行排序。下面是一些背景知识

我有一个
模式
对象,它有许多
字段
。用户指定这些值序列化的顺序(如果存在),如下所示:

id、dateTime、payload
这些值应该存在于架构中。如果没有,我会过滤掉它们。我对用户想要什么和模式喜欢什么执行交集,因此:

  private List<Field> performIntersection(List<String> subsetFields, List<Field> allFields) {
    return allFields.stream()
        .distinct()
        .filter(field -> subsetFields.contains(field.name()))
        .collect(Collectors.toList());
  }
您可以与查看列表中项目索引的比较器一起使用

return allFields.stream()
    .distinct()
    .filter(field -> subsetFields.contains(field.name()))
    .sorted(Comparator.comparingInt(field -> subsetFields.indexOf(field.name())))
    .collect(Collectors.toList());
您可以与查看列表中项目索引的比较器一起使用

return allFields.stream()
    .distinct()
    .filter(field -> subsetFields.contains(field.name()))
    .sorted(Comparator.comparingInt(field -> subsetFields.indexOf(field.name())))
    .collect(Collectors.toList());

如果您关心效率,特别是当列表可能很大时,您应该避免重复的线性搜索,如
contains
indexOf
,这将使操作的时间复杂度为O(n×m)。使用具有高效查找的临时映射将提供O(n+m)时间复杂性:

private List<Field> performIntersection(List<String> subsetFields, List<Field> allFields){
  Map<String, Field> all = allFields.stream()
      .collect(Collectors.toMap(Field::name, Function.identity(), (a,b)->a));
  return subsetFields.stream()
      .map(all::get).filter(Objects::nonNull).collect(Collectors.toList());
}
private List performinterssection(列出子字段,列出所有字段){
Map all=allFields.stream()
.collect(Collectors.toMap(Field::name,Function.identity(),(a,b)->a));
返回subsetFields.stream()
.map(all::get).filter(Objects::nonNull).collect(Collectors.toList());
}
请注意,使用
(a,b)->a
作为
toMap
的合并函数意味着在重复键的情况下“保留上一个”,这与代码中的
distinct()
具有相同的效果(假设字段的唯一性由其名称决定)


此外,结果已经具有所需的顺序,而不需要排序,因为它来自
子字段上的流。我使用
filter(Objects::nonNull)
来消除
所有字段中不存在的
子字段的名称,就像您的代码所做的那样。如果名称总是映射到一个现有的
字段
,您可以删除此筛选步骤。

如果您关心效率,特别是当列表可能很大时,您应该避免重复线性搜索,如
包含
索引
,这将使操作具有O(n×m)时间复杂性。使用具有高效查找的临时映射将提供O(n+m)时间复杂性:

private List<Field> performIntersection(List<String> subsetFields, List<Field> allFields){
  Map<String, Field> all = allFields.stream()
      .collect(Collectors.toMap(Field::name, Function.identity(), (a,b)->a));
  return subsetFields.stream()
      .map(all::get).filter(Objects::nonNull).collect(Collectors.toList());
}
private List performinterssection(列出子字段,列出所有字段){
Map all=allFields.stream()
.collect(Collectors.toMap(Field::name,Function.identity(),(a,b)->a));
返回subsetFields.stream()
.map(all::get).filter(Objects::nonNull).collect(Collectors.toList());
}
请注意,使用
(a,b)->a
作为
toMap
的合并函数意味着在重复键的情况下“保留上一个”,这与代码中的
distinct()
具有相同的效果(假设字段的唯一性由其名称决定)


此外,结果已经具有所需的顺序,而不需要排序,因为它来自
子字段上的流。我使用
filter(Objects::nonNull)
来消除
所有字段中不存在的
子字段的名称,就像您的代码所做的那样。如果名称总是映射到现有的
字段
,则可以删除此筛选步骤。

项目中的
字段
是一个类吗?否。字段是ApacheI know contains中的一个Avro字段,因为它会扫描N个项目的列表,但会取消订单。我知道排队可以,但如果我开始排队的话就太乱了polling@Bohemian我添加的工作代码对我来说太难看了,我不想使用,但是我想要的是你的项目中的一个类。不是。字段是Apache中的一个Avro字段。我知道contains在这里弄乱了它,因为它会扫描N个项目的列表,但它会破坏订单。我知道排队可以,但如果我开始排队的话就太乱了polling@Bohemian我添加的工作代码对我来说太难看了,我不想使用,但却能理解我的意思want@Ryan当然没有problem@Ryan当然,没问题