This commit is contained in:
Looly
2021-11-16 01:19:40 +08:00
parent 22c69f6c49
commit 50654f821f
9 changed files with 115 additions and 55 deletions

View File

@@ -7,6 +7,7 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.Matcher;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.text.finder.CharFinder;
import cn.hutool.core.text.finder.Finder;
import cn.hutool.core.text.finder.StrFinder;
import cn.hutool.core.util.ArrayUtil;
@@ -1066,7 +1067,7 @@ public class CharSequenceUtil {
* @param searchChar 被查找的字符
* @return 位置
*/
public static int indexOf(final CharSequence str, char searchChar) {
public static int indexOf(CharSequence str, char searchChar) {
return indexOf(str, searchChar, 0);
}
@@ -1089,33 +1090,17 @@ public class CharSequenceUtil {
/**
* 指定范围内查找指定字符
*
* @param str 字符串
* @param text 字符串
* @param searchChar 被查找的字符
* @param start 起始位置如果小于0从0开始查找
* @param end 终止位置如果超过str.length()则默认查找到字符串末尾
* @return 位置
*/
public static int indexOf(final CharSequence str, char searchChar, int start, int end) {
if (isEmpty(str)) {
public static int indexOf(CharSequence text, char searchChar, int start, int end) {
if (isEmpty(text)) {
return INDEX_NOT_FOUND;
}
final int len = str.length();
if (start < 0 || start > len) {
start = 0;
}
if (end > len) {
end = len;
}
if (end < 0) {
end += len;
}
for (int i = start; i < end; i++) {
if (str.charAt(i) == searchChar) {
return i;
}
}
return INDEX_NOT_FOUND;
return new CharFinder(searchChar).setText(text).setEndIndex(end).start(start);
}
/**
@@ -1237,7 +1222,8 @@ public class CharSequenceUtil {
return INDEX_NOT_FOUND;
}
}
return new StrFinder(searchStr, ignoreCase, true).setText(text).start(from);
return new StrFinder(searchStr, ignoreCase)
.setText(text).setNegative(true).start(from);
}
/**

View File

@@ -39,10 +39,18 @@ public class CharFinder extends TextFinder {
@Override
public int start(int from) {
Assert.notNull(this.text, "Text to find must be not null!");
final int limit = getValidEndIndex(false);
for (int i = from; i < limit; i++) {
if (NumberUtil.equals(c, text.charAt(i), caseInsensitive)) {
return i;
final int limit = getValidEndIndex();
if(negative){
for (int i = from; i > limit; i--) {
if (NumberUtil.equals(c, text.charAt(i), caseInsensitive)) {
return i;
}
}
} else{
for (int i = from; i < limit; i++) {
if (NumberUtil.equals(c, text.charAt(i), caseInsensitive)) {
return i;
}
}
}
return -1;

View File

@@ -26,10 +26,18 @@ public class CharMatcherFinder extends TextFinder {
@Override
public int start(int from) {
Assert.notNull(this.text, "Text to find must be not null!");
final int limit = getValidEndIndex(false);
for (int i = from; i < limit; i++) {
if(matcher.match(text.charAt(i))){
return i;
final int limit = getValidEndIndex();
if(negative){
for (int i = from; i > limit; i--) {
if(matcher.match(text.charAt(i))){
return i;
}
}
} else {
for (int i = from; i < limit; i++) {
if(matcher.match(text.charAt(i))){
return i;
}
}
}
return -1;

View File

@@ -25,10 +25,18 @@ public class LengthFinder extends TextFinder {
@Override
public int start(int from) {
Assert.notNull(this.text, "Text to find must be not null!");
final int result = from + length;
final int limit = getValidEndIndex(false);
if(result < limit){
return result;
final int limit = getValidEndIndex();
int result;
if(negative){
result = from - length;
if(result > limit){
return result;
}
} else {
result = from + length;
if(result < limit){
return result;
}
}
return -1;
}

View File

@@ -41,11 +41,16 @@ public class PatternFinder extends TextFinder {
return super.setText(text);
}
@Override
public TextFinder setNegative(boolean negative) {
throw new UnsupportedOperationException("Negative is invalid for Pattern!");
}
@Override
public int start(int from) {
if (matcher.find(from)) {
// 只有匹配到的字符串结尾在limit范围内才算找到
if(matcher.end() <= getValidEndIndex(false)){
if(matcher.end() <= getValidEndIndex()){
return matcher.start();
}
}

View File

@@ -14,7 +14,6 @@ public class StrFinder extends TextFinder {
private final CharSequence strToFind;
private final boolean caseInsensitive;
private final boolean negative;
/**
* 构造
@@ -23,21 +22,9 @@ public class StrFinder extends TextFinder {
* @param caseInsensitive 是否忽略大小写
*/
public StrFinder(CharSequence strToFind, boolean caseInsensitive) {
this(strToFind, caseInsensitive, false);
}
/**
* 构造
*
* @param strToFind 被查找的字符串
* @param caseInsensitive 是否忽略大小写
* @param negative 是否从后向前查找模式
*/
public StrFinder(CharSequence strToFind, boolean caseInsensitive, boolean negative ) {
Assert.notEmpty(strToFind);
this.strToFind = strToFind;
this.caseInsensitive = caseInsensitive;
this.negative = negative ;
}
@Override
@@ -48,15 +35,15 @@ public class StrFinder extends TextFinder {
if (from < 0) {
from = 0;
}
int endLimit = getValidEndIndex(negative);
if(negative){
int endLimit = getValidEndIndex();
if (negative) {
for (int i = from; i > endLimit; i--) {
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
return i;
}
}
} else {
endLimit = endLimit - subLen + 1;
endLimit = endLimit - subLen + 1;
for (int i = from; i < endLimit; i++) {
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
return i;

View File

@@ -15,6 +15,7 @@ public abstract class TextFinder implements Finder, Serializable {
protected CharSequence text;
protected int endIndex = -1;
protected boolean negative;
/**
* 设置被查找的文本
@@ -40,21 +41,31 @@ public abstract class TextFinder implements Finder, Serializable {
return this;
}
/**
* 设置是否反向查找,{@code true}表示从后向前查找
*
* @param negative 结束位置(不包括)
* @return this
*/
public TextFinder setNegative(boolean negative) {
this.negative = negative;
return this;
}
/**
* 获取有效结束位置<br>
* 如果{@link #endIndex}小于0在反向模式下是开头-1正向模式是结尾text.length()
*
* @param negative 是否从后向前查找模式
* @return 有效结束位置
*/
protected int getValidEndIndex(boolean negative) {
protected int getValidEndIndex() {
if(negative && -1 == endIndex){
// 反向查找模式下,-1表示0前面的位置即字符串反向末尾的位置
return -1;
}
final int limit;
if (endIndex < 0) {
limit = endIndex + text.length();
limit = endIndex + text.length() + 1;
} else {
limit = Math.min(endIndex, text.length());
}

View File

@@ -47,5 +47,22 @@ public class CharSequenceUtilTest {
Assert.assertEquals(str1, str2);
}
// ------------------------------------------------------------------------ remove
@Test
public void indexOfTest(){
int index = CharSequenceUtil.indexOf("abc123", '1');
Assert.assertEquals(3, index);
index = CharSequenceUtil.indexOf("abc123", '3');
Assert.assertEquals(5, index);
index = CharSequenceUtil.indexOf("abc123", 'a');
Assert.assertEquals(0, index);
}
@Test
public void indexOfTest2(){
int index = CharSequenceUtil.indexOf("abc123", '1', 0, 3);
Assert.assertEquals(-1, index);
index = CharSequenceUtil.indexOf("abc123", 'b', 0, 3);
Assert.assertEquals(1, index);
}
}

View File

@@ -0,0 +1,30 @@
package cn.hutool.core.text.finder;
import org.junit.Assert;
import org.junit.Test;
public class CharFinderTest {
@Test
public void startTest(){
int start = new CharFinder('a').setText("cba123").start(2);
Assert.assertEquals(2, start);
start = new CharFinder('c').setText("cba123").start(2);
Assert.assertEquals(-1, start);
start = new CharFinder('3').setText("cba123").start(2);
Assert.assertEquals(5, start);
}
@Test
public void negativeStartTest(){
int start = new CharFinder('a').setText("cba123").setNegative(true).start(2);
Assert.assertEquals(2, start);
start = new CharFinder('2').setText("cba123").setNegative(true).start(2);
Assert.assertEquals(-1, start);
start = new CharFinder('c').setText("cba123").setNegative(true).start(2);
Assert.assertEquals(0, start);
}
}