HashSet 中意外的空键,第一个被添加而不是其余的

An unexpected null key in HashSet, the first be added not the rest

我正在学习Activiti 7,我画了一个BPMN图如下: highlight1 UserTask 已完成但 highlight2 UserTask 仍未决时,我 运行 以下代码突出显示已完成的流程元素。

private AjaxResponse highlightHistoricProcess(@RequestParam("instanceId") String instanceId,
      @AuthenticationPrincipal UserInfo userInfo) {
    try {
      // Get the instance from the history table
      HistoricProcessInstance instance = historyService
          .createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
      BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
      Process process = bpmnModel.getProcesses().get(0);
      // Get all process elements, including sequences, events, activities, etc.
      Collection<FlowElement> flowElements = process.getFlowElements();
      Map<String, String> sequenceFlowMap = Maps.newHashMap();
      flowElements.forEach(e -> {
        
        if (e instanceof SequenceFlow) {
          SequenceFlow sequenceFlow = (SequenceFlow) e;
          String sourceRef = sequenceFlow.getSourceRef();
          String targetRef = sequenceFlow.getTargetRef();
          sequenceFlowMap.put(sourceRef + targetRef, sequenceFlow.getId());
        }
      });

      // Get all historical Activities, i.e. those that have been executed and those that are currently being executed
      List<HistoricActivityInstance> actList = historyService.createHistoricActivityInstanceQuery()
          .processInstanceId(instanceId)
          .list();

      // Each history Activity is combined two by two
      Set<String> actPairSet = new HashSet<>();
      for (HistoricActivityInstance actA : actList) {
        for (HistoricActivityInstance actB : actList) {
          if (actA != actB) {
            actPairSet.add(actA.getActivityId() + actB.getActivityId());
          }
        }
      }

      // Highlight Link ID 
      Set<String> highSequenceSet = Sets.newHashSet();
      actPairSet.forEach(actPair -> {
        logger.info("actPair:{}, seq:{}", actPair, sequenceFlowMap.get(actPair));
        highSequenceSet.add(sequenceFlowMap.get(actPair));
        logger.info("{}",highSequenceSet.toString());
      });

      // Get the completed Activity
      List<HistoricActivityInstance> finishedActList = historyService
          .createHistoricActivityInstanceQuery()
          .processInstanceId(instanceId)
          .finished()
          .list();

      // Highlight the completed Activity
      Set<String> highActSet = Sets.newHashSet();
      finishedActList.forEach(point -> highActSet.add(point.getActivityId()));

      // Get the pending highlighted node, i.e. the currently executing node
      List<HistoricActivityInstance> unfinishedActList = historyService
          .createHistoricActivityInstanceQuery()
          .processInstanceId(instanceId)
          .unfinished()
          .list();
      Set<String> unfinishedPointSet = Sets.newHashSet();
      unfinishedActList.forEach(point -> unfinishedPointSet.add(point.getActivityId()));

      ...
      return AjaxResponse.ajax(ResponseCode.SUCCESS.getCode(),
          ResponseCode.SUCCESS.getDesc(),
          null);
    } catch (Exception e) {
      e.printStackTrace();
      return AjaxResponse.ajax(ResponseCode.ERROR.getCode(),
          "highlight failure",
          e.toString());
    }
  }

请看这段代码:

      // Highlight Link ID 
      Set<String> highSequenceSet = Sets.newHashSet();
      actPairSet.forEach(actPair -> {
        logger.info("actPair:{}, seq:{}", actPair, sequenceFlowMap.get(actPair));
        highSequenceSet.add(sequenceFlowMap.get(actPair));
        logger.info("{}",highSequenceSet.toString());
      });

本应在 highSequenceSet 中得到 2 个元素,但得到了 3 个,出乎意料 null。 控制台打印的日志是:

为什么第一个 null 添加到 HashSet 而其余的没有?

Why is the first null added to the HashSet but not the rest?

HashSet实现了Set接口,不允许重复值。