首页 > 解决方案 > 在 java 中使用字符串替换方法时面临的问题

问题描述

我正在努力支持 Kindle 设备上的通知。我们从服务器接收到包含主题的表达式 sting(主题将用单引号括起来)。我们需要检查设备是否订阅了主题。如果已订阅,则需要将逻辑表达式中的主题替换为“1”,否则替换为“0”。下面是逻辑表达式的示例。

('18' in topics || '4' in topics) && ('REG_92779' in topics && 'REG_91212' in topics)

假设设备订阅了主题“18”、“4”而不订阅“REG_92779”和“REG_91212”。表达式应该变成

('1' || '1') && ('0' && '0')

之后,我们需要删除空格和引号。表达式应该变成

(1||1)&&(0&0)

下面是代码

private boolean checkNotificationValid(String leString) {
        // Remove the 'in topics' string. examples of logical expression as below
        // ('4' in topics && '50000' in topics) || ('60' in topics || '3' in topics)
        // ('4' in topics && ('50000' in topics || '60' in topics))
        leString = leString.replaceAll("in topics", "");
        Log.d(TAG, "Notifications : ADM : LE : Logical Expression received : " + leString);
        boolean result = false;

        // Find the topics in the logical expression and check whether the device is subscribed to
        // the topic. If device is subscribed to the topic, replace the topic with 1 or replace the
        // topic with 0. Below is the example.
        // Assume device is subscribed to topics 3 and 4.
        // Expression : ('4' && '50000') || ('60' || '3')
        // After this block of code, it becomes : ('1' && '0') || ('0' || '1')
        Pattern p = Pattern.compile("'(.*?)'");
        Matcher m = p.matcher(leString);
        while(m.find()) {
            Log.d(TAG, "Notifications : ADM : LE : " + m.group(1));

            // Check whether the device is subscribed to the topic
            if(NotificationUtils.isTopicExistInSharedPref(m.group(1))) {
                leString = leString.replaceFirst(m.group(1), "1");
            } else {
                leString = leString.replaceFirst(m.group(1), "0");
            }
        }

        // Remove the quotes and spaces from the string, replace '||' with '|', replace '&&' with '&'
        // ('1' && '0') || ('0' || '1') -> (1&0)|(0|1)
        leString = leString.replaceAll("[' ]", "");
        leString = leString.replaceAll("\\|\\|", "|");
        leString = leString.replaceAll("&&", "&");

        return result;
    }

代码工作正常。但如果主题是“1”或“0”,则失败。下面是例子,

('18' in topics || '4' in topics) && ('1' in topics && '1' in topics)

在前 2 个主题(18 和 4)验证后,字符串变为

('1' || '1') && ('1' && '1')

现在对于主题“1”,当我尝试用 0 替换时(因为未订阅设备),它正在替换第一个“1”,它应该替换第三个“1”。它正在变成如下。

('0' || '1') && ('1' && '1')

它应该变成

('1' || '1') && ('0' && '1')

主题“0”也发生了同样的问题。

发生这种情况是因为我使用了 replaceFirst() 方法。如果我尝试使用 replace() ,它将替换字符串中的所有匹配项,而不是替换特定主题。谁能帮我解决这个问题。

注意:我首先根据设备订阅替换为 1 或 0,后来我删除了引号 ('4' -> '1' -> 1),因为我不知道如何将主题替换为 1 或 0 ( '4' -> 1)。

标签: java

解决方案


代替使用replaceFirstof String,您可以使用StringBuffer和追加替换appendReplacement方法 of Matcher

您的代码将变为:

private boolean checkNotificationValid(String leString) {
    leString = leString.replaceAll("in topics", "");
    Log.d(TAG, "Notifications : ADM : LE : Logical Expression received : " + leString);
    boolean result = false;

    StringBuffer buffer = new StringBuffer();
    Pattern p = Pattern.compile("'(.*?)'");
    Matcher m = p.matcher(leString);
    while(m.find()) {
        Log.d(TAG, "Notifications : ADM : LE : " + m.group(1));

        if(NotificationUtils.isTopicExistInSharedPref(m.group(1))) {
            m.appendReplacement(buffer, "1");
        } else {
            m.appendReplacement(buffer, "0");
        }
    }

    m.appendTail(buffer);
    String finalStr = buffer.toString();
    finalStr = finalStr.replaceAll("[' ]", "");
    finalStr = finalStr.replaceAll("\\|\\|", "|");
    finalStr = finalStr.replaceAll("&&", "&");

    return result;
}

推荐阅读