使用Pattern、Matcher来实现搜索高亮显示

需求很简单,做一个搜索功能,要求搜索结果高亮显示。
1、最简单直接的方法,使用string的indexOf方法,来获取关键字的为准,然后做高亮处理。但是这样如果文本里多次出现关键字,就不太好弄了;
2、使用正则表达式判断:
使用正则表达式当然是一个好办法,但是很少人能直接写出正则表达式,那怎么办呢?别急Java里自带了封装好的类来帮助我们实现,它就是Pattern和Matcher!
具体用法大家可以自己去百度Google一下,这里不详细介绍了,只说一下我在实现高亮的时候遇到的问题以及解决方法。
下面下把代码供出来:

public static SpannableStringBuilder highlight(String text, String target) {

        SpannableStringBuilder spannable = new SpannableStringBuilder(text);
        CharacterStyle span = null;

        Pattern p = Pattern.compile(target,Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(text);
        while (m.find()) {
            span = new ForegroundColorSpan(Color.RED);
            spannable.setSpan(span, m.start(), m.end(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return spannable;
    }

主要就是通过SpannableStringBuilder来显示高亮,然后通过Pattern和Matcher来解析。
其中Pattern.compile(target,Pattern.CASE_INSENSITIVE); 表示不区分大小写。
本来挺好的一个功能,突然测试人员提了一个崩溃的bug,在输入框中输入“+”的时候会导致app crash。这是什么情况?自己试了一下,发现报错信息如下:


Caused by: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1:
E/AndroidRuntime(17429):+
E/AndroidRuntime(17429): ^
E/AndroidRuntime(17429): at java.util.regex.Pattern.compileImpl(Native Method)
E/AndroidRuntime(17429): at java.util.regex.Pattern.compile(Pattern.java:400)

虽然知道是特殊符号导致的,但是经过测试发现并不是所有的特殊符号都会出现这个问题。
那有哪些特殊符号会导致呢?

正则表达式中有一类叫做“元字符(meta-character)”的特殊符号,它们并不匹配自身对应的字符,而具有其他的含义。比如脱字符『^』表示“定位到字符串/行的开头”,加号『+』表示“之前的元素重现1次以上。如果需要匹配这些字符本身,需要用反斜线来转义,匹配『^』就应该用\^,匹配『+』就应该用+。

看起来有点麻烦,但这样的元字符并不多:^$()*+?.[{|

这就好办了,最简单粗暴的办法就是:

final static String PATTERN_SYMBOL = "^$()*+?.[\\{|";
if (PATTERN_SYMBOL.contains(target)){
    target = "\\"+target;//对正则表达式保留符号进行转义
}

对于这些特殊符号做转义。
虽然这样可以实现,但是总觉得不够“优雅”,有没有更方便、更优雅的解决办法呢?答案是肯定的!
还记得在创建Pattern 时的flag——Pattern.CASE_INSENSITIVE,既然能不区分大小写,那能不能转义元字符呢?
点进Pattern类,发现里面定义了好多静态flag,其中有一个

 /**
     * This constant specifies that the whole {@code Pattern} is to be taken
     * literally, that is, all meta characters lose their meanings.
     */
public static final int LITERAL = 0x10;

注释大致意思就是说 所有字符都是按照字面意思来,所有的元字符都失去了它们的意义。那不正是我们想要的吗?
试了一下,果然好用!
当然有人还想不区分大小写,又要使用元字符,那怎么办呢?

Pattern p = Pattern.compile(target,Pattern.LITERAL|Pattern.CASE_INSENSITIVE);

这么写,搞定!

参考文档:
http://www.cnblogs.com/ajianbeyourself/p/5709567.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: patternmatcherJava中用于正则表达式匹配的类。 Pattern类表示一个正则表达式,可以通过Pattern.compile()方法将一个字符串编译成一个Pattern对象。Matcher类则是用于匹配字符串的工具类,可以通过Pattern.matcher()方法将一个字符串与一个Pattern对象进行匹配。 使用时,先创建一个Pattern对象,然后通过matcher()方法创建一个Matcher对象,最后调用Matcher对象的find()、group()等方法进行匹配和提取匹配结果。 例如,以下代码可以匹配一个字符串中的所有数字: ``` String str = "abc123def456"; Pattern pattern = Pattern.compile("\\d+"); Matcher matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); } ``` 输出结果为: ``` 123 456 ``` ### 回答2: Java提供了PatternMatcher两个类用于处理字符串的匹配。其中,Pattern类表示正则表达式的编译结果,Matcher类则可以通过正则表达式对字符串进行匹配。 使用PatternMatcher的过程大致如下:首先,使用Pattern.compile()方法将正则表达式编译成一个Pattern对象,然后使用Matcher类的匹配方法对字符串进行匹配。 Pattern类的compile()方法可以接受一个表示正则表达式的字符串作为参数,返回一个Pattern对象。此时,我们可以使用Matcher类的matcher()方法返回一个Matcher对象,Matcher对象的matches()方法可以用来判断这个字符串是否匹配该正则表达式。 在使用Matcher类的前提下,我们可以使用find()方法进行字符串的匹配,找到第一个满足正则表达式的子序列。 例如,我们可以使用如下的代码对一个字符串进行匹配: Pattern p = Pattern.compile("abc"); Matcher m = p.matcher("abcdefg"); if (m.find()) { System.out.println("Found!"); } 以上代码会找到字符串中第一个匹配"abc"的子序列,并输出"Found!"的信息。 除此之外,Matcher类还有其它的方法可以对字符串进行操作,例如replaceFirst()方法和replaceAll()方法可以用来替换字符串中符合正则表达式的子序列,group()方法可以用来返回匹配的子序列,等等。 总体来说,PatternMatcher使用可以方便地进行对字符串的匹配和处理,可以应用于许多场景,如数据校验、文本分析等。但是在使用正则表达式时,也需要注意其复杂性和性能问题,需要根据具体场景选择合适的正则表达式和算法来处理数据。 ### 回答3: PatternMatcherJava正则表达式的核心类库,它们的使用可以帮助我们对字符串进行灵活的匹配和查找,是Java中非常常用的工具。 首先,我们需要先创建一个Pattern对象,以指定要匹配的模式。这可以通过Pattern类的静态compile方法实现,该方法接受一个正则表达式字符串作为参数,并返回一个Pattern对象。例如,我们可以使用如下代码来创建一个匹配所有数字的Pattern对象: ``` Pattern pattern = Pattern.compile("\\d+"); ``` 这里的\\d表示任意数字字符,+表示该字符可以重复1次或多次。注意,由于Java中\也是转义字符,因此需要使用双斜杠来表示一个\字符。 接着,我们可以通过Matcher类的静态方法matches来判断一个字符串是否匹配指定的模式。例如,我们可以使用如下代码来判断字符串str是否全部由数字组成: ``` boolean isMatch = pattern.matcher(str).matches(); ``` 如果该字符串匹配指定的模式,则返回true,否则返回false。 除了matches方法外,Matcher类还提供了很多其他的方法,例如find方法可以在字符串中查找第一个匹配模式的子串,并返回一个Match对象,通过该对象可以获取匹配的结果;group方法可以获取匹配的子串;start和end方法可以获取匹配子串在原字符串中的起始和结束位置等等。这些方法可以配合正则表达式一起使用,非常强大和灵活。 需要注意的是,由于正则表达式的复杂性和性能问题,在处理大量数据时建议尽量减少使用正则表达式,以提高程序的运行效率。同时,也应该对正则表达式的语法有充分的了解,以避免出现不必要的问题和错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值