【问题标题】:How To Count The Number of Times a String Occurs如何计算字符串出现的次数
【发布时间】:2018-07-30 15:26:03
【问题描述】:

所以我为我的代码创建了一条错误消息。目前,我的代码每次出现时都会吐出错误消息。我的代码验证并确保 excel 文件的格式正确。验证后,如果发生错误/警告消息,它会返回。因此,当我收到错误消息时,每条消息都会在每次发生时出现。例如,验证 excel 文件时出现 6 次错误消息“错误,id 不得包含特殊字符”。有什么方法可以简单地写来检查消息是否已经发生,并记录多少次以便我可以显示?

我想过像if (message = message) { //then create counter} 这样的东西,但这不起作用,因为消息总是等于消息。有人有办法吗?

编辑:这是用于验证的代码片段。我想将消息组合在一起,并且在发布到 API 时不让它们重复。

        // if there are errors, then
        if (!errorResponse.getItems().isEmpty()) {

            // set error response
            Iterator<ErrorMessage> iter = errorResponse.getItems().iterator();

            Set<ErrorMessage> summarizedErrorMessages = new HashSet<>();

            while (iter.hasNext()) {
                ErrorMessage sem = new ErrorMessage();
                ErrorMessage em = iter.next();
                if (!summarizedErrorMessages.contains(em)) {
                    sem.setMessage(em.getMessage());
                    sem.setTotal(1);
                } else {
                    sem.setTotal(sem.getTotal() + 1);
                }
                summarizedErrorMessages.add(sem);
            }
            errorResponse.setItems(summarizedErrorMessages);
            warningResponse.setItems(new ArrayList<WarningMessage>());

【问题讨论】:

  • 您只想比较两个字符串吗?如果是,请使用.equals
  • 请分享您的代码。
  • 使用Hashmap &lt;String, Integer &gt; map,这映射 Message 和 count ,您可以将所有可能的消息计数为零,然后在发生错误情况时更新(增加)计数。

标签: java error-handling counter


【解决方案1】:

HashMap&lt;String,Integer&gt; 将使用String 的哈希码作为键,因此相同的String 将映射到地图中的相同位置。

因此,您可以在第一次看到消息字符串时(当它不在地图中时)将消息字符串以 1 的计数推送到地图中,然后再将其递增:

HashMap<String,Integer> messageCounts = new HashMap<>();
messages.forEach( message -> {
    messageCounts.putIfAbsent( message, 0 );
    messageCounts.computeIfPresent( message, (k,v) -> v+1 );
});

因此,对于您的具体情况,可能是这样的:

// First map messages to counts
HashMap<String,Integer> messageCounts = new HashMap<>();
errorResponse.getItems().forEach( errorMessage -> {
    messageCounts.putIfAbsent( errorMessage.getMessage(), 0 );
    messageCounts.computeIfPresent( errorMessage.getMessage(), (k,v) -> v+1 );
});

// Then create the summary objects
List<ErrorMessages> summaries = 
    messageCounts.entrySet().stream().map( e -> {
        ErrorMessage summary = new ErrorMessage();
        summary.setMessage( e.getKey() );
        summary.setTotal( e.getValue() );
        return summary;
    } ).collect( Collectors.toList() );

errorResponse.setItems( summaries );

【讨论】:

  • 你的意思是HashMap&lt;String, Integer&gt;
  • 这种方法的问题是,由于变量太多,我可以产生很多不同的消息。我正在寻找一种方法来做到这一点,而不必对所有可能发生的选项进行硬编码
  • @ArnaudDenoyelle 哎呀,是的,Kotlin 太多了:D 我会编辑帖子。
  • @nico43624 我添加了一个与您发布的代码匹配的示例。这是否使它更清楚?您的代码重复的原因是您每次都在循环中创建一个新的ErrorMessage。将它与add() 一起放入if( ...contains()) 块中,它可能会起作用。
  • @davedupplaw 您的新更新代码非常有帮助,但是 .map() 正在抛出错误,原因我不知道。我目前正在尝试您的其他建议,看看是否可行。
【解决方案2】:

使用HashMap&lt;String, Long&gt;,其中键是错误消息,值是错误发生的次数。

收到错误消息时,检查if map.containsKey(message),然后获取计数器(long counter = map.get(message)),将其递增并放回映射中(map.put(message, counter + 1L))。

如果地图不包含消息,则将其添加到地图并将计数器初始化为 1 (map.put(message, 1L))。

类似这样的:

private Map<String, Long> errors = new HashMap<String, Long>();

public void handleError(String error) {
    if(errors.containsKey(error)) {
        Long counter = errors.get(error);
        errors.put(error, counter + 1L);
    } else {
        errors.put(error, 1L);
    }
}

测试

handleError("Error, id must not contain special characters");
handleError("StackOverflow");
handleError("Error, id must not contain special characters");
handleError("Error, id must not contain special characters");
handleError("StackOverflow");

for (Map.Entry<String, Long> entry : errors.entrySet()) {
    System.out.println(entry.getKey() + " : " + entry.getValue());
}

输出

StackOverflow : 2
Error, id must not contain special characters : 3

【讨论】:

  • 我的消息是一个名为 errorResponse 的自定义变量。这些错误消息必须作为一个集合进入系统,因此我无法将其设为地图,因为从地图到集合的转换在这里不起作用。
【解决方案3】:

只是在这里创建一个单独的答案,这样我就可以发布适用于这个问题的完整代码。这是没有错误的代码:

            // if there are errors, then
        if (!errorResponse.getItems().isEmpty()) {

            // set error response
            Iterator<ErrorMessage> iter = errorResponse.getItems().iterator();

            HashMap<String, Integer> messageCounts = new HashMap<String, Integer>();
            errorResponse.getItems().forEach(ErrorMessage -> {
                messageCounts.putIfAbsent(ErrorMessage.getMessage(), 1);
                messageCounts.computeIfPresent(ErrorMessage.getMessage(), (k, v) -> v + 1);
            });

            Set<ErrorMessage> summaries = new HashSet<>();
            for (String s : messageCounts.keySet()) {
                ErrorMessage summary = new ErrorMessage();
                summary.setMessage(s);
                summary.setTotal(messageCounts.get(s));
                summaries.add(summary);
            }

            errorResponse.setItems(summaries);
            warningResponse.setItems(new ArrayList<WarningMessage>());

【讨论】:

    猜你喜欢
    • 2012-10-03
    • 2010-09-21
    • 2012-06-24
    • 2014-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多