java - Java - 如何比较不同对象类型的列表
问题描述
我希望我能清楚地解释我的问题。
我正在开发一个 API 网关,以将 JSON 有效负载与外部 API (Okta) 进行比较,以了解为有效负载的每个对象执行哪个 HTTP 操作。
通常我会简单地在外部 API 上发出一个 GET 请求并比较两个 JSON,这会更容易。但是对于这个我使用 Okta 的 API SDK ( https://github.com/okta/okta-sdk-java ) 来发出这些请求,尤其是不必通过 POJO 定义我需要的所有对象我的项目。
所以我将我的 JSON 有效负载放入一个List
由元素组成的元素Group
(这是我想要使用的 SDK 中的一个元素)。然后,我使用 SDK 通过 API 获取 Okta 中的元素,并将其放入List
也 of elementGroup
中。这是代码:
List<Group> groupListBody = mapper.readValue(body, List.class);
List<Group> groupListOkta = okta.listGroups().stream().collect(Collectors.toList());
问题是 List 实际上由不同类型的 Objects 组成:
- JSON有效负载列表是
List
一个LinkedHashMap
对象 - Okta 列表是
List
一个DefaultGroup
对象
但是,如果我们取 和 的一个元素,groupListBody
因为groupListOkta
它们是由 object 定义的Group
,我们可以清楚地看到它们除了类型之外是相同的。
所以我的问题是,我能做些什么来改变它们的类型或其他东西来正确比较这两个列表的元素?
更新 :
我注意到杰克逊创建了一个列表,LinkedHashMap
因为它没有足够的信息将我的有效负载反序列化为Group
对象列表。
如果我将列表中的一个元素用
Group test = (Group) groupListBody.get(0);
ERROR::class java.util.LinkedHashMap cannot be cast to class com.okta.sdk.resource.group.Group (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.okta.sdk.resource.group.Group is in unnamed module of loader 'app')
我认为它来自Group
对象的 SDK 模型,但我不知道如何在不重新创建 POJO 模型的情况下正确反序列化它。
这是模型类:
public interface Group extends ExtensibleResource, Deletable {
Map<String, Object> getEmbedded();
Map<String, Object> getLinks();
Date getCreated();
String getId();
Date getLastMembershipUpdated();
Date getLastUpdated();
List<String> getObjectClass();
GroupProfile getProfile();
Group setProfile(GroupProfile profile);
GroupType getType();
Role assignRole(AssignRoleRequest assignRoleRequest, String disableNotifications);
Role assignRole(AssignRoleRequest assignRoleRequest);
UserList listUsers();
Group update();
void removeUser(String userId);
ApplicationList listApplications();
void delete();
}
解决方案
编辑:我已经阅读了您帖子的更新。如果您确实必须比较这两种对象类型而不将它们复制到新列表中,您可能会发现这种方法很有用:
在 Java 中,我们有 Collector 接口,它是一个通用接口,定义如下:
Public interface collector <T,A,R>{
Supplier<A> supplier();
BiConsumer<A,T> accumulator()
BinaryOperator<A> combiner()
Function<A,R> finisher();
Set<characteristics> characteristics();
}
现在,我们可以通过定义一个实现我上面提供的所有方法的新类来实现这个接口的自定义收集器。但首先,这一切到底意味着什么?
元素<T,A,R>: -T 是流提供的元素的对象类型 -A 累加器在收集元素时将调用的对象类型 -R 收集方法返回的对象类型
方法: -Supplier() 提供保存累积操作结果的容器。Supplier 是一个工厂函数,它返回对方法的引用。-accumulator() 消耗元素以累积它们 -combiner() 统一累积结果 -finisher() 将保存累积结果的容器转换为所需类型 -characteristics() 定义流以并行或顺序计算运行时的行为(例如:并发或无序)。
如果这种方法对您不起作用,我们可以通过一些有用的方法来更好地控制输入数据的输出。
List<Group> groupListOkta =
okta.listGroups().stream().collectAndThen(Collector<T,A,R>
downstream, Function<R,RR> modifier()) //Passes the collector
//to a finisher function, in which you can return the desired type.
如果您想阅读有关该主题的更多信息,这里有一些有用的链接:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toCollection-java.util.function.Supplier- https://docs.oracle.com/javase/ 8/docs/api/java/util/stream/Collectors.html https://www.technetexperts.com/web/how-to-use-custom-collectors-in-java/ https://docs.oracle.com /javase/8/docs/api/java/util/stream/Collectors.html#collectingAndThen-java.util.stream.Collector-java.util.function.Function-
再会,
虽然有点乏味,但您可以编写一个循环遍历对象的所有元素的函数,然后创建一个新的布尔数组列表。此列表将为您提供其索引处的所有匹配项。
public static List<Boolean> checkMatches( List<Group> l1, List<Group> l2 ) {
//Optionally, you can check here which list is shortest and store
//this somewhere, enabling you to preset matches.length
List<Boolean> matches = new ArrayList<>();
int count = 0;
for ( Object o1 : l2 ) {
count++
for ( Object o2 : l1 ) {
if (o1.equals(o2){
matches.add(true)
};
};
if (matches.length < count){
matches.add(false)
};
};
return matches;
};
这个想法是,如果在其他对象中找到匹配项,则添加 true,然后通过比较长度检查是否添加了 true,如果没有添加 true,则添加 false。
推荐阅读
- python - 将 textwrap.fill 应用于 python 脚本上的每个打印
- javascript - JavaScript 中的 new Object() 发生了什么
- java - 关于 Java 10 语法规范的困惑(FieldAccess 似乎是错误的)
- graphql - graphql,将大查询拆分为小查询
- c# - 如何对隐藏在其他元素中的字典进行 XML 反序列化?
- android - LibGDX 错误:程序类型已存在
- mysql - MySQL 未在 XAMPP MacOS 上启动
- git - 恢复这些文件后,文件是否会在下一次 git pull 时被删除?
- symfony - 如何通过一对多双向获取第二个实体的数据
- java - SonarQube 从 jacoco 结果计算错误的代码覆盖率