[英]Java - How to compare list of different Object types
我希望我能足够清楚地解释我的问题。
我正在开发一个 API 网关来将 JSON 有效负载与外部 API (Okta) 进行比较,以了解对有效负载的每个对象执行哪个 HTTP 操作。
通常我会简单地在外部 API 上发出一个 GET 请求并比较两个 JSON,这会更容易。 但是对于这个,我使用 Okta 的 API SDK ( https://github.com/okta/okta-sdk-java ) 来发出这些请求,尤其是不必通过 POJO 定义我需要的所有对象我的项目。
所以我将我的 JSON 负载放入一个由元素Group
(这是我想要使用的 SDK 中的元素)组成的List
。 然后我使用 SDK 通过 API 获取 Okta 中的元素,并将其放入元素Group
的List
中。 这是代码:
List<Group> groupListBody = mapper.readValue(body, List.class);
List<Group> groupListOkta = okta.listGroups().stream().collect(Collectors.toList());
问题是 List 实际上由不同类型的 Objects 组成:
LinkedHashMap
对象List
DefaultGroup
对象的List
但是,如果我们采用对象Group
定义的groupListBody
和groupListOkta
元素,我们可以清楚地看到它们除了类型之外是相同的。
所以我的问题是,我能做些什么来改变它们的类型或其他东西来正确比较这两个列表的元素?
更新 :
我注意到 jackson 创建了一个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 collect 方法返回的对象类型
方法: -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。 我相信你可以让它更漂亮、更高效。 我希望该解决方案对您有用!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.