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

如何使用Java Streams统计单词出现次数并记录其所在句子?

Solution: Track Word Frequency and Sentence IDs in Java

Great question! You've already got the basics of counting word frequencies down, and your intuition about using IntStream.range to track sentence IDs is spot-on—let's build on that to get the exact output you need.

Step 1: Define a Helper Class to Hold Word Statistics

First, we need a clean way to store both the total count of each word and the list of sentence IDs it appears in. A simple helper class will keep this organized:

static class WordStats {
    int totalCount;
    Set<Integer> sentenceIds;

    public WordStats() {
        this.totalCount = 0;
        this.sentenceIds = new HashSet<>(); // Use Set to avoid duplicate sentence IDs
    }
}

We use a Set for sentence IDs because if a word appears multiple times in the same sentence, we only want to list that sentence once (matching your example output).

Step 2: Process Each Sentence with Its ID

Instead of flattening all words first (which loses sentence context), we'll iterate over each sentence along with its 1-based ID. Here's the full implementation:

static void getWordSentenceStats(List<String> inputLines) {
    // Initialize a map to track stats for each word
    Map<String, WordStats> wordStatsMap = new HashMap<>();

    // Iterate over each sentence with its 1-based ID
    IntStream.range(0, inputLines.size())
            .forEach(i -> {
                int sentenceId = i + 1; // Convert 0-index to 1-based ID
                String sentence = inputLines.get(i);

                // Split sentence into words, clean up, and convert to lowercase
                String[] words = sentence.split("[^a-zA-Z0-9]+");
                Arrays.stream(words)
                        .map(String::toLowerCase)
                        .filter(word -> !word.isEmpty()) // Skip empty strings from split
                        .forEach(word -> {
                            // Get or create WordStats for the word
                            WordStats stats = wordStatsMap.computeIfAbsent(word, k -> new WordStats());
                            stats.totalCount++; // Increment total occurrence count
                            stats.sentenceIds.add(sentenceId); // Add the current sentence ID
                        });
            });

    // Print results in your desired format
    wordStatsMap.forEach((word, stats) -> {
        // Convert sentence IDs set to a sorted, comma-separated string
        String ids = stats.sentenceIds.stream()
                .sorted()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
        System.out.printf("%s:{%d:%s} %n", word, stats.totalCount, ids);
    });
}

Step 3: Test the Code

Let's run this with your sample input to confirm it matches your expected output:

public static void main(String[] args) {
    List<String> sentences = Arrays.asList(
            "Question, what kind of wine is best?",
            "White wine.",
            "A question"
    );
    getWordSentenceStats(sentences);
}

Output:

a:{1:3} 
best:{1:1} 
is:{1:1} 
kind:{1:1} 
of:{1:1} 
question:{2:1,3} 
what:{1:1} 
white:{1:2} 
wine:{2:1,2} 

(Note: The order may vary slightly since HashMap is unordered—use TreeMap instead if you need alphabetically sorted words.)

Key Details:

  • computeIfAbsent: This method simplifies checking if a word exists in the map—if not, it automatically creates a new WordStats instance for it.
  • Filtering empty strings: Splitting sentences with punctuation can sometimes produce empty strings (e.g., if a sentence ends with a comma), so we filter those out to avoid counting invalid "words".
  • Sorted sentence IDs: We sort the sentence IDs in the output to match your example's ordered list.

内容的提问来源于stack exchange,提问作者ocuenca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:54:05