使用收集器根据 Java 中的 class 将 Steam 拆分为列表
Using Collectors to split steam into lists based on class in Java
以下代码是伪代码,表示我要实现的目标:
Map<Class<?>, List<?>> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass));
List<Integer> ints = map.get(Integer.class);
List<String> strings = map.get(String.class);
以上是简化的代码。我想要的是我有一个输入列表,我想根据对象的 class 将它分成多个列表。
但是上面的代码无法编译,请问您如何修复它?
您可以使用 List<Object>
而不是 List<?>
:
Map<Class<?>, List<Object>> map = Stream.of(1, "2")
.collect(Collectors.groupingBy(Object::getClass));
List<Object> ints = map.get(Integer.class);
List<Object> strings = map.get(String.class);
可以通过将 List<?>
更改为 List<Object>
来修复第一行:
Map<Class<?>, List<Object>> map = Stream.of(1, "2")
.collect(Collectors.groupingBy(Object::getClass));
接下来的几行问题更多。我不认为有任何方法可以在 Java 中定义那种通用关系。你将不得不使用丑陋的、不安全的转换:
List<Integer> ints = (List)map.get(Integer.class);
List<String> strings = (List)map.get(String.class);
如果你想让它更安全和用户友好,你可以把它隐藏在一个自定义的后面class:
class TypeToListMap {
private Map<Class<?>, List<Object>> map = ...
public <T> List<T> get(Class<T> key) {
@SuppressWarnings("unchecked")
List<T> result = (List<T>)map.get(key);
return result;
}
}
好的类型:
Stream.of(1, "2");
实际上是:
Stream<?> stream = Stream.of(1, "2");
在这种情况下,?
的唯一合法替代是 Object
。
因为类型擦除 ?
将是对象。
这就像你需要在运行时用泛型声明你的列表的类型。就像这样做:
T x;
List<x.getClass()> list = ...; // can't do that
你可以在这里做一个 hack 并施放两次 :)
@SuppressWarnings("unchecked")
List<Integer> ints = (List<Integer>) (List<?>) map.get(Integer.class);
其实你可以直接投结果。列表实际上应该由所需类型的对象组成,所以应该没有问题。不过,您可能会收到编译器警告(如果您向编译器指定要接收未经检查的转换警告)。
Map<Class, ?> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass));
List<Integer> ints = (List<Integer>) map.get(Integer.class);
List<String> strings = (List<String>) map.get(String.class);
以下代码是伪代码,表示我要实现的目标:
Map<Class<?>, List<?>> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass));
List<Integer> ints = map.get(Integer.class);
List<String> strings = map.get(String.class);
以上是简化的代码。我想要的是我有一个输入列表,我想根据对象的 class 将它分成多个列表。
但是上面的代码无法编译,请问您如何修复它?
您可以使用 List<Object>
而不是 List<?>
:
Map<Class<?>, List<Object>> map = Stream.of(1, "2")
.collect(Collectors.groupingBy(Object::getClass));
List<Object> ints = map.get(Integer.class);
List<Object> strings = map.get(String.class);
可以通过将 List<?>
更改为 List<Object>
来修复第一行:
Map<Class<?>, List<Object>> map = Stream.of(1, "2")
.collect(Collectors.groupingBy(Object::getClass));
接下来的几行问题更多。我不认为有任何方法可以在 Java 中定义那种通用关系。你将不得不使用丑陋的、不安全的转换:
List<Integer> ints = (List)map.get(Integer.class);
List<String> strings = (List)map.get(String.class);
如果你想让它更安全和用户友好,你可以把它隐藏在一个自定义的后面class:
class TypeToListMap {
private Map<Class<?>, List<Object>> map = ...
public <T> List<T> get(Class<T> key) {
@SuppressWarnings("unchecked")
List<T> result = (List<T>)map.get(key);
return result;
}
}
好的类型:
Stream.of(1, "2");
实际上是:
Stream<?> stream = Stream.of(1, "2");
在这种情况下,?
的唯一合法替代是 Object
。
因为类型擦除 ?
将是对象。
这就像你需要在运行时用泛型声明你的列表的类型。就像这样做:
T x;
List<x.getClass()> list = ...; // can't do that
你可以在这里做一个 hack 并施放两次 :)
@SuppressWarnings("unchecked")
List<Integer> ints = (List<Integer>) (List<?>) map.get(Integer.class);
其实你可以直接投结果。列表实际上应该由所需类型的对象组成,所以应该没有问题。不过,您可能会收到编译器警告(如果您向编译器指定要接收未经检查的转换警告)。
Map<Class, ?> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass));
List<Integer> ints = (List<Integer>) map.get(Integer.class);
List<String> strings = (List<String>) map.get(String.class);