You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将自定义Counting类作为容器使用Stream.collect方法?

问题及代码

我是一名学生,您可能觉得我在代码中做了不必要的冗余操作,但我的目的只是加深对collect方法的理解。所有提及的组件都属于本次主题范畴,我的目标是解决报错问题,而非寻找实现相同结果的其他方法,请勿提供替代方案!提前感谢。

以下是我的代码:

package konekcija;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToolBar;

import java.awt.EventQueue;
import java.sql.*;
import java.util.HashMap;
import java.util.Queue;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.Map.Entry;
public class app {

  private JFrame okvir;
  private JList lst;
  private JLabel[] conn = new JLabel[20];
  private JTextField txt;
  private JPanel[] pnl = new JPanel[20];
  private JButton query[] = new JButton[20];
  private JToolBar box;

  public static void main(String[] args) {

    EventQueue.invokeLater(() -> {
      var app = new app();
      app.okvir.setVisible(true);

    });
  }

  public app() {
    this.initialize();

  }
record Counting(HashMap<JPanel,Integer> hm){
public Counting() {
  this(new HashMap<JPanel,Integer> ());// odnos glavnog yapisa i adicionih svojstava u nekanonskom konstrunktu
  
}
  public void accumulator(JPanel p) {
    this.hm.put(p, 1);
    
  }
    
   // samo da ukazem na to da se iako su polja kao u nekoj POJO oznakom final, ne znaci da je sadrzaj ref konacan
    public void combiner(Counting cn) {
      var key = cn.hm().keySet().stream().findFirst().get();
   this.hm.put(key, (int)this.hm.getOrDefault(key,0)+1);
  
    }
    }
private void initialize() {


   okvir = new JFrame();
  okvir.getContentPane().setLayout(null);
  okvir.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  okvir.setBounds(000, 0000, 1880, 1880);
  okvir.setResizable(false);
okvir.setTitle("PREDUZEĆE");



  Stream.of( (Stream.of(this.pnl).limit(3)
      .collect(new Counting(),(c,p)->((Counting) c).accumulator(p), 
             (c1,c2)->((Counting) c2).combiner((Counting) 
              c1))).hm().entrySet()).peek((entry)->{
                   var idx=entry.getValue();
                   var pnl=entry.getKey();
                   switch(idx) {
                         case 1:
                            pnl.setBounds(0,0,idx*100,100);
                            break;
                         case 2:
                            pnl.setBounds(0,0,idx*100,100);
                            break;
                         case 3:
                            pnl.setBounds(0,0,idx*100,100);
                            break;
                         default:
                            break;
                        }
                   }).close();
} }

问题描述

问题出在collect相关部分,程序无法识别自定义的Counting record作为容器供应者。我在书中见过类似的用法,或是使用HashMap、List等预定义类,但原理应该一致。我哪里出错了?需要说明的是,collect部分出现错误后,我凭记忆编写了后续的流操作,只是为了代码完整,现在我需要修复collect相关部分。这里我使用了两个流,一个从传入的Counting实例中获取hm字段,提取entrySet并生成新的外部流。


解决方法

核心错误点

  1. collect的供应者参数类型错误:
    collect方法的第一个参数需要的是Supplier<R>(无参构造器引用或Lambda),而非直接传入一个实例。你直接传new Counting()不符合方法签名,应该用Counting::new来提供容器的创建逻辑。

  2. 流的创建错误:
    Stream.of(this.pnl)会生成Stream<JPanel[]>(把整个数组当成单个元素),而你需要的是数组中每个JPanel的流,应该用Arrays.stream(this.pnl)。

  3. 累加器/组合器的冗余强制转换:
    由于供应者指定了类型,累加器和组合器的参数类型可以被自动推断,不需要强制转换(Counting) c,这会导致类型推断混乱。

  4. Combiner逻辑缺陷:
    当前的combiner只处理了传入Counting实例中的第一个key,应该遍历所有entry进行合并,否则并行流场景下会丢失数据。

修复后的代码片段

修正Counting的combiner方法

public void combiner(Counting cn) {
    // 遍历传入的Counting中的所有entry,合并到当前实例的HashMap中
    for (Entry<JPanel, Integer> entry : cn.hm().entrySet()) {
        this.hm.put(entry.getKey(), this.hm.getOrDefault(entry.getKey(), 0) + entry.getValue());
    }
}

修正initialize中的collect调用

// 先导入Arrays
import java.util.Arrays;

// 替换原collect相关代码
Counting countingResult = Arrays.stream(this.pnl)
    .limit(3)
    .collect(Counting::new, Counting::accumulator, Counting::combiner);

// 后续处理entrySet的流
Stream.of(countingResult.hm().entrySet())
    .peek(entry -> {
        var idx = entry.getValue();
        var pnl = entry.getKey();
        switch (idx) {
            case 1:
                pnl.setBounds(0, 0, idx * 100, 100);
                break;
            case 2:
                pnl.setBounds(0, 0, idx * 100, 100);
                break;
            case 3:
                pnl.setBounds(0, 0, idx * 100, 100);
                break;
            default:
                break;
        }
    }).close();

说明

  • 用Arrays.stream正确遍历数组元素
  • collect的三个参数分别为:容器供应者(Counting::new)、累加器方法引用(Counting::accumulator)、组合器方法引用(Counting::combiner),完全符合collect的方法签名
  • 修正后的combiner能正确合并所有元素,不管是串行还是并行流都能正常工作

内容的提问来源于stack exchange,提问作者Saerujeji Reebu CHINA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:59:53