During the development and review process of the disk health indicator we noticed that it was hard to understand. Since we learnt a lot from the first round of development we want to go through the code one more time and restructure it.
server/src/main/java/org/elasticsearch/health/node/DiskHealthIndicatorService.java
return clusterState.nodes()
            .getNodes()
            .values()
            .stream()
            .filter(node -> nodeIds.contains(node.getId()))
            .filter(node -> node.getRoles().stream().anyMatch(DiscoveryNodeRole::canContainData))
            .map(DiscoveryNode::getId)
            .collect(Collectors.toSet());
    }
    
    static Set<String> getNodesWithMasterRole(Set<String> nodeIds, ClusterState clusterState) {
        return clusterState.nodes()
            .getNodes()
            .values()
            .stream()
            .filter(node -> nodeIds.contains(node.getId()))
            .filter(node -> node.canContainData() == false && node.isMasterNode())
            .map(DiscoveryNode::getId)
            .collect(Collectors.toSet());
    }
    
    static Set<String> getNodesWithNonDataNonMasterRoles(Set<String> nodeIds, ClusterState clusterState) {
        return clusterState.nodes()
            .getNodes()
            .values()
            .stream()
            .filter(node -> nodeIds.contains(node.getId()))
            .filter(node -> node.canContainData() == false && node.isMasterNode() == false)
            .map(DiscoveryNode::getId)
            .collect(Collectors.toSet());