检测并返回Java字符串中的字符

时间:2013-02-01 11:21:29

标签: java regex string

我正在尝试编写一个方法来扫描字符串中的某些字符,然后报告找到了哪些字符(如果有的话):

// Special characters are ~, #, @, and *
// If text == "Hello~Clarice, you're s#o ambitious", then this
// method should return a string == "~#". If no special characters
// found, return null. If the same special character occurs 2+ times,
// ignore it and do not return strings with duplicate special chars, like
// "##@***", etc. --> just "#@*".
public String detectAndGetSpecialCharacters(String text) {
    Pattern p = Pattern.compile("[~#@*]");
    Matcher m = pattern.matcher(text);

    String specialCharactersFound = null;
    if(m.find()) {
        // ???
    }

    return specialCharactersFound;
}

我已经完成了此方法的 detect 部分,但我很难找到一种有效/优雅的方式来使用Matcher告诉我哪个发现了特殊字符,并且将它们连接在一起(删除重复!)并返回它们。提前谢谢!

3 个答案:

答案 0 :(得分:4)

为什么不简单地使用String.indexOf(specialChar)。如果结果为> = 0,则为每个特殊字符调用此方法,这意味着特殊字符至少存在一次。

然后根据找到的索引对特殊字符进行排序,以构建重新排列的字符串。

不是很优雅,但我认为这很有效,因为:

  • 您不必删除重复项。
  • 如果您有许多(重复)特殊字符,则不会产生任何影响

编辑(这是示例代码)

    private static class SpecialChar implements Comparable<SpecialChar>{
        Integer position;
        char c;

        private SpecialChar(char c, Integer position) {
            this.c = c;
            this.position = position;
        }

        @Override
        public int compareTo(SpecialChar another) {
            return position.compareTo(another.position);
        }
    }

    public static void main(String[] args){
        String input = args[0];
        char[]  specialsChars = new char[]{'*','@','~','#'};
        List<SpecialChar> results = new ArrayList<SpecialChar>();
        for(char c:specialsChars){
            int position = input.indexOf(c);
            if(position>-1)results.add(new SpecialChar(c,position));
        }
        Collections.sort(results);
        StringBuilder builder = new StringBuilder();
        for(SpecialChar sp:results){
            builder.append(sp.c);
        }
        System.out.print(builder.toString());
   }

答案 1 :(得分:2)

您可以使用StringBuilder,而不是使用字符串,并将每个匹配的字符附加到它,如果它不存在: -

StringBuilder builder = new StringBuilder();
while (m.find()) {
    String str = m.group();
    if (!builder.toString().contains(str)) {
        builder.append(str);
    }
}

// And finally
return builder.toString();

另一种方法是维护Set<String>,并继续为其添加匹配的字符。它会自动删除重复项。然后,您可以使用Apache Commons StringUtils#join()方法合并Set的值以形成String。或者您可以简单地遍历Set并将每个字符串附加到StringBuilder对象。无论你喜欢什么样的方式都适合。

答案 2 :(得分:0)

您需要capturing-group。用括号括起你的正则表达式,并为每个matcher#find得到它。它将类似于:

public String detectAndGetSpecialCharacters(String text) {
    Pattern p = Pattern.compile("([~#@*])");
    Matcher m = pattern.matcher(text);
    Set<String> specialCharacters = new HashSet<String>();

    if (m.find()) {
        specialCharacters.add(m.group(1));
    }
    StringBuilder specialCharactersFound = new StringBuilder();

    for (String specialChar : specialCharacters) {
        specialCharactersFound.append(specialChar);
    }
    return specialCharactersFound.toString();
}

添加到Set将删除重复项,并在最后使用特殊字符构建String。并且它不会返回null,这通常不是一件好事。


修改

您实际上并不需要捕获组,因为您的正则表达式只获取特殊字符。你可以使用Matcher#group。但是,学习更多东西是件好事;)