java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap不能强制转换为java.util.LinkedHashMap
很抱歉,我就这个一般性问题提出了另一个问题,但我发现的所有问题似乎都与我的问题没有密切关系 我有一个现有的工作数据流管道,它接受java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap不能强制转换为java.util.LinkedHashMap,java,google-cloud-dataflow,apache-beam,dataflow,Java,Google Cloud Dataflow,Apache Beam,Dataflow,很抱歉,我就这个一般性问题提出了另一个问题,但我发现的所有问题似乎都与我的问题没有密切关系 我有一个现有的工作数据流管道,它接受KV的对象并输出TableRow对象。这段代码在我们的生产环境中运行,没有问题。然而,我现在正试图用direct runner实现一个单元测试来测试这个管道,但是当它上线时,单元测试失败了 LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Sch
KV
的对象并输出TableRow
对象。这段代码在我们的生产环境中运行,没有问题。然而,我现在正试图用direct runner实现一个单元测试来测试这个管道,但是当它上线时,单元测试失败了
LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Schema.EVT);
导致问题的行是gson.fromJson(EVENTS[i],TableRow.class)代码>,它似乎将TableRow的内部表示形式编码为错误类型的LinkedTreeMap
TableRow的编码类型似乎是com.google.gson.internal.LinkedTreeMap
,而不是预期的java.util.LinkedHashMap
。是否有一种方法可以将单元测试中创建的TableRow转换为正确类型的java.util.LinkedHashMap
,因此,单元测试在不更改已在生产中运行的现有数据流代码的情况下成功?这是因为LinkedHashMap并不优于LinkedTreeMap,因此它们可能没有相同的方法。Java编译器因此认为,以这种方式强制转换它可能会导致evt
具有与row.get(Schema.evt)
不同的方法,从而产生不好的结果。
但是,您可以将LinkedTreeMap转换为AbstractMap、Map或Object,因为它们都优于它。
所以(正如许多评论所指出的)要修复它,只需使用
Map<String, Object> evt = row.get(Schema.EVT);
Map evt=row.get(Schema.evt);
<> P>你应该是好的。 < P>我会考虑(不仅仅是那个)。每次对cast进行编码时,都有发生ClassCastException
的风险
正如其他人已经说过的,Map
接口可以像Map evt=row.get(Schema.evt)那样使用代码>
或者,可以通过newlinkedhashmap(row.get(Schema.EVT)),构建一个新的LinkedHashMap
代码>
第二种方法的优点是保留LinkedHashMap
类型,这可能很重要,也可能不重要,这取决于您的场景。将解决方案作为答案重新发布
如果不使用具体类的特定功能,则不建议强制转换为具体类。在这种情况下,最好转换为Map
,而不是LinkedHashMap
。Gson的LinkedTreeMap
也是一个Map
,所以不会出现问题。请告诉我是否需要更多的代码来添加上下文。为什么你需要转换到LinkedHashMap
,而不仅仅是转换到Map
?@RomanPuchkovskiy说实话,我不确定。对LinkedHashMap
的转换是以前的代码。将演员阵容更改为Map
会有任何后果吗?没错。根据接口编码并将LinkedHashMap
替换为Map
。那么您就不必关心API恰好返回了哪个映射实现。@Max如果LinkedTreeMap
是map
的子类,那么这应该不是问题,除非您使用该类中的特定内容。但我认为你最好的办法就是试试看它是否有效
Map<Long, List<TableRow>> groups = new HashMap<Long, List<TableRow>>();
List<KV<Long, Iterable<TableRow>>> collections = new ArrayList<KV<Long,Iterable<TableRow>>>();
Gson gson = new Gson();
// populate the map with events grouped by id
for(int i = 0; i < EVENTS.length; i++) {
TableRow row = gson.fromJson(EVENTS[i], TableRow.class);
Long id = EVENT_IDS[i];
if(groups.containsKey(id))
groups.get(id).add(row);
else
groups.put(id, new ArrayList<TableRow>(Arrays.asList(row)));
}
// prepare main input for pipeline
for(Long key : groups.keySet())
collections.add(KV.of(key, groups.get(key)));
Map<String, Object> evt = row.get(Schema.EVT);