以下代码有效且可读,但在我看来,我认为不需要中间操作。我编写了这个简化版本,因为实际代码是一个更大过程的一部分。
我有一个Collectionof Widget,每个都有一个名称和多种类型(由WidgetType枚举的常量表示)。这些多种类型都是可以获取的,Stream<WidgetType>但如果有必要,我可以将它们作为其他类型返回。(出于各种原因,强烈希望将它们作为 a 返回,Stream<WidgetType>因为稍后在实际代码中如何使用这些小部件。)
这些小部件被添加到 ,EnumMap<WidgetType, List<Widget>>然后被翻译成EnumMap<WidgetType, Widget[]>.
如果每个都Widget只有一个WidgetType,这将是一个微不足道的解决方案,但是,由于任何 Widget 都可能有 1 个或多个类型,因此我会被Collectors.groupingBy()方法的语法(及其重载)绊倒。
这是代码示例,再次,功能齐全,并为我提供了我需要的确切结果。
class StackOverFlowExample {
private final Map<WidgetType, Widget[]> widgetMap = new EnumMap<>(WidgetType.class);
public static void main(String[] args) { new StackOverFlowExample(); }
StackOverFlowExample() {
Collection<Widget> widgetList = getWidgetsFromWhereverWidgetsComeFrom();
{
final Map<WidgetType, List<Widget>> intermediateMap = new EnumMap<>(WidgetType.class);
widgetList.forEach(w ->
w.getWidgetTypes().forEach(wt -> {
intermediateMap.putIfAbsent(wt, new ArrayList<>());
intermediateMap.get(wt).add(w);
}) …Run Code Online (Sandbox Code Playgroud) 考虑简单的类Foo:
public class Foo {
public Float v1;
public Float v2;
public String name;
public Foo(String name, Float v1, Float v2) {
this.name = name;
this.v1 = v1;
this.v2 = v2;
}
public String getName() {
return name;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我有一个Foos的集合,我想将它们按Foo::getName. 我写了一个自定义收集器来做到这一点,但它似乎没有按预期工作。更准确地说,combiner()永远不会被调用。为什么?
public class Main {
public static void main(String[] args) {
List<Foo> foos = new ArrayList<>();
foos.add(new Foo("blue", 2f, 2f));
foos.add(new Foo("blue", 2f, 3f));
foos.add(new Foo("green", 3f, 4f));
Map<String, Float> fooGroups …Run Code Online (Sandbox Code Playgroud) 我试图将整数列表转换为逗号分隔整数的字符串。
Collectors.joining(CharSequence delimiter) - 返回一个收集器,它按遇到顺序连接输入元素,由指定的分隔符分隔。
List<Integer> i = new ArrayList<>(); // i.add(null);
for (int j = 1; j < 6; j++) {
i.add(j);
}
System.out.println(i.stream().collect(Collectors.joining(","))); // Line 8
Run Code Online (Sandbox Code Playgroud)
我在第 8 行出错。
有没有办法通过 Java 8 中的流来做到这一点?
更新:
如果我用"1", "2", "3","4","5". 有用。
我需要计算一些特殊捆绑包的出现次数。
Map<Integer,Integer> countBundles(){
return bundles.stream()
.bla()
.bla()
.bla()
.collect(groupingBy(Bundle::getId), counting()));
}
Run Code Online (Sandbox Code Playgroud)
此代码无法编译,因为计数返回 Long。有什么漂亮的方法返回 Map<Integer, Integer> 吗?
我有这个想法,但是很难看
map.entrySet().stream()
.collect(toMap(Map.Entry::getKey, entry -> (int) entry.getValue().longValue()));
Run Code Online (Sandbox Code Playgroud) 我制作了一个自定义收集器,它使用 MessageDigest 来创建哈希。一般来说,MessageDigest 不能并行工作。我看到的问题在于combiner()方法。无法组合两个 MessageDigest 对象。当我返回 null 时,它似乎可以工作,但如果我抛出一个,UnsupportedOperationException它就会失败。实现不支持并行操作的收集器的典型方法是什么?
class ChecksumCollector implements Collector<String, MessageDigest, ByteBuffer> {
private String algorithm;
ChecksumCollector(final String algorithm) {
this.algorithm = algorithm;
}
@Override
public Supplier<MessageDigest> supplier() {
return () -> {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException("Could not find MessageDigest for algorithm " + algorithm, e);
}
};
}
@Override
public BiConsumer<MessageDigest, String> accumulator() {
return (md, s) -> md.update(s.getBytes(StandardCharsets.UTF_8));
}
@Override
public BinaryOperator<MessageDigest> combiner() { …Run Code Online (Sandbox Code Playgroud) 我有下面的代码并基于布尔值进行 groupingBy
Map<Boolean, List<Test>> products = testList
.stream()
.collect(Collectors.groupingBy(Test::isValidUser));
Run Code Online (Sandbox Code Playgroud)
我想把它收集起来Map<String, List<Test> 。
基于布尔值,想要将自定义键添加为“有效”和“无效”。
如果为isValidUsertrue,则要将密钥添加为“有效”,否则密钥应为“无效”
在 Java 11 中是否有可能做到这一点?
注意:没有在Test类中添加String变量
给定以下类Order和Item以及 s 的列表Order。
@Getter
@AllArgsConstructor
@ToString
public class Order {
String customerName;
List<Item> items;
}
@Getter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Item {
long id;
String name;
}
Run Code Online (Sandbox Code Playgroud)
我需要创建一个映射Map<String,Set<String>> itemsByCustomerName,其中键是客户名称以及属于该客户名称Order的所有名称的一组名称。Item
输入示例:
List<Order> orders = List.of(
new Order("John", List.of(new Item(1, "A"), new Item(2, "B"), new Item(3, "C"))),
new Order("Alex", List.of(new Item(1, "A"), new Item(8, "H"), new Item(11, "K"))),
new Order("John", List.of(new Item(1, "A"), new Item(6, "F"), new Item(7, "G"))),
new …Run Code Online (Sandbox Code Playgroud) 如何创建Map<String,List<Product>> 如下。这里,String(的keyMap ) 是categorya 的Product。
一种产品可以属于多个类别,如下例所示。
我正在尝试使用以下代码,但无法进行下一步操作:
products.stream()
.flatMap(product -> product.getCategories().stream())
. // how should I progress from here?
Run Code Online (Sandbox Code Playgroud)
结果应如下所示:
{电子=[p1,p3,p4], 时尚=[p1,p2,p4], 厨房=[p1,p2,p3], abc1=[p2], xyz1=[p3],pqr1=[p4]}
Product p1 = new Product(123, Arrays.asList("electonics,fashion,kitchen".split(",")));
Product p2 = new Product(123, Arrays.asList("abc1,fashion,kitchen".split(",")));
Product p3 = new Product(123, Arrays.asList("electonics,xyz1,kitchen".split(",")));
Product p4 = new Product(123, Arrays.asList("electonics,fashion,pqr1".split(",")));
List<Product> products = Arrays.asList(p1, p2, p3, p4);
Run Code Online (Sandbox Code Playgroud)
class Product {
int price;
List<String> categories;
public Product(int price) { …Run Code Online (Sandbox Code Playgroud) 我通过实现Collector接口并覆盖其方法来实现自定义收集器.Collector实现如下:
class MyCustomCollector implements Collector<Person, StringJoiner, String>{
@Override
public Supplier<StringJoiner> supplier() {
// TODO Auto-generated method stub
return () -> new StringJoiner("|");
}
@Override
public BiConsumer<StringJoiner, Person> accumulator() {
// TODO Auto-generated method stub
return (joiner,person) -> joiner.add(person.name.toUpperCase());
}
@Override
public BinaryOperator<StringJoiner> combiner() {
// TODO Auto-generated method stub
return (joiner1, joiner2) -> joiner1.merge(joiner2);
}
@Override
public Function<StringJoiner, String> finisher() {
// TODO Auto-generated method stub
return StringJoiner::toString;
}
@Override
public Set<java.util.stream.Collector.Characteristics> characteristics() {
// TODO Auto-generated method stub
return …Run Code Online (Sandbox Code Playgroud) 以下代码是一个伪代码,表示我想要实现的目标:
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);
Run Code Online (Sandbox Code Playgroud)
以上是简化的代码.我想要的是我有一个输入列表,我想根据对象的类将它拆分成多个列表.
但是上面的代码没有编译,我想知道你怎么能解决它?
collectors ×10
java-stream ×10
java ×9
java-8 ×5
groupingby ×2
collections ×1
hashmap ×1
integer ×1