implement lastIndexOf
This commit is contained in:
parent
68cb8af7e4
commit
dee8f6fb84
|
@ -216,6 +216,8 @@ static int lastIndexOf(final CharSequence cs, final int searchChar, int start) {
|
|||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
static final int TO_STRING_LIMIT = 16;
|
||||
|
||||
/**
|
||||
* Used by the lastIndexOf(CharSequence methods) as a green implementation of lastIndexOf
|
||||
*
|
||||
|
@ -224,24 +226,66 @@ static int lastIndexOf(final CharSequence cs, final int searchChar, int start) {
|
|||
* @param start the start index
|
||||
* @return the index where the search sequence was found
|
||||
*/
|
||||
static int lastIndexOf(final CharSequence cs, final CharSequence searchChar, final int start) {
|
||||
if (cs instanceof String) {
|
||||
return ((String) cs).lastIndexOf((String) searchChar, start);
|
||||
} else if (cs instanceof StringBuilder) {
|
||||
return ((StringBuilder) cs).lastIndexOf((String) searchChar, start);
|
||||
} else if (cs instanceof StringBuffer) {
|
||||
return ((StringBuffer) cs).lastIndexOf((String) searchChar, start);
|
||||
static int lastIndexOf(final CharSequence cs, final CharSequence searchChar, int start) {
|
||||
if (searchChar instanceof String) {
|
||||
if (cs instanceof String) {
|
||||
return ((String) cs).lastIndexOf((String) searchChar, start);
|
||||
} else if (cs instanceof StringBuilder) {
|
||||
return ((StringBuilder) cs).lastIndexOf((String) searchChar, start);
|
||||
} else if (cs instanceof StringBuffer) {
|
||||
return ((StringBuffer) cs).lastIndexOf((String) searchChar, start);
|
||||
}
|
||||
}
|
||||
return cs.toString().lastIndexOf(searchChar.toString(), start);
|
||||
// if (cs instanceof String && searchChar instanceof String) {
|
||||
// // TODO: Do we assume searchChar is usually relatively small;
|
||||
// // If so then calling toString() on it is better than reverting to
|
||||
// // the green implementation in the else block
|
||||
// return ((String) cs).lastIndexOf((String) searchChar, start);
|
||||
// } else {
|
||||
// // TODO: Implement rather than convert to String
|
||||
// return cs.toString().lastIndexOf(searchChar.toString(), start);
|
||||
// }
|
||||
|
||||
int len1 = cs.length();
|
||||
int len2 = searchChar.length();
|
||||
|
||||
if (start > len1) {
|
||||
start = len1;
|
||||
}
|
||||
|
||||
if (start < 0 || len2 < 0 || len2 > len1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len2 == 0) {
|
||||
return start;
|
||||
}
|
||||
|
||||
if (len2 <= TO_STRING_LIMIT) {
|
||||
if (cs instanceof String) {
|
||||
return ((String) cs).lastIndexOf(searchChar.toString(), start);
|
||||
} else if (cs instanceof StringBuilder) {
|
||||
return ((StringBuilder) cs).lastIndexOf(searchChar.toString(), start);
|
||||
} else if (cs instanceof StringBuffer) {
|
||||
return ((StringBuffer) cs).lastIndexOf(searchChar.toString(), start);
|
||||
}
|
||||
}
|
||||
|
||||
if (start + len2 > len1) {
|
||||
start = len1 - len2;
|
||||
}
|
||||
|
||||
if (check(cs, searchChar, len2, start)) {
|
||||
return start;
|
||||
}
|
||||
|
||||
for (int i = start - 1; i >= 0; i--) {
|
||||
if (check(cs, searchChar, len2, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static boolean check(final CharSequence cs, final CharSequence searchChar, int len2, int start1) {
|
||||
for (int i = 0; i < len2; i++) {
|
||||
if (cs.charAt(start1 + i) != searchChar.charAt(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.commons.lang3;
|
||||
|
||||
import static java.nio.CharBuffer.wrap;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -26,7 +27,11 @@
|
|||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.commons.lang3.text.StrBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
|
@ -186,4 +191,94 @@ public void testToCharArray() {
|
|||
assertArrayEquals(expected, CharSequenceUtils.toCharArray(builder.toString()));
|
||||
}
|
||||
|
||||
static class WrapperString implements CharSequence {
|
||||
CharSequence inner;
|
||||
|
||||
public WrapperString(CharSequence inner) {
|
||||
this.inner = inner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return inner.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return inner.charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return inner.subSequence(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return inner.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntStream chars() {
|
||||
return inner.chars();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntStream codePoints() {
|
||||
return inner.codePoints();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewLastIndexOf() {
|
||||
testNewLastIndexOfSingle("808087847-1321060740-635567660180086727-925755305", "-1321060740-635567660", 21);
|
||||
testNewLastIndexOfSingle("", "");
|
||||
testNewLastIndexOfSingle("1", "");
|
||||
testNewLastIndexOfSingle("", "1");
|
||||
testNewLastIndexOfSingle("1", "1");
|
||||
testNewLastIndexOfSingle("11", "1");
|
||||
testNewLastIndexOfSingle("1", "11");
|
||||
|
||||
Random random = new Random();
|
||||
StringBuilder seg = new StringBuilder();
|
||||
while (seg.length() <= CharSequenceUtils.TO_STRING_LIMIT) {
|
||||
seg.append(random.nextInt());
|
||||
}
|
||||
StringBuilder original = new StringBuilder(seg);
|
||||
testNewLastIndexOfSingle(original, seg);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (random.nextDouble() < 0.5) {
|
||||
original.append(random.nextInt() % 10);
|
||||
} else {
|
||||
original = new StringBuilder().append(String.valueOf(random.nextInt() % 100)).append(original);
|
||||
}
|
||||
testNewLastIndexOfSingle(original, seg);
|
||||
}
|
||||
}
|
||||
|
||||
private void testNewLastIndexOfSingle(CharSequence a, CharSequence b) {
|
||||
int maxa = Math.max(a.length(), b.length());
|
||||
for (int i = -maxa-10; i <= maxa+10; i++) {
|
||||
testNewLastIndexOfSingle(a, b, i);
|
||||
}
|
||||
}
|
||||
|
||||
private void testNewLastIndexOfSingle(CharSequence a, CharSequence b, int start) {
|
||||
testNewLastIndexOfSingleSingle(a, b, start);
|
||||
testNewLastIndexOfSingleSingle(b, a, start);
|
||||
}
|
||||
|
||||
private void testNewLastIndexOfSingleSingle(CharSequence a, CharSequence b, int start) {
|
||||
int expected = a.toString().lastIndexOf(b.toString(), start);
|
||||
// assertEquals(
|
||||
// expected,
|
||||
// lastIndexOf(new WrapperString(a), b, start),
|
||||
// "testNewLastIndexOf fails! original : " + a + " seg : " + b + " start : " + start
|
||||
// );
|
||||
assertEquals(
|
||||
expected,
|
||||
CharSequenceUtils.lastIndexOf(new WrapperString(a.toString()), b.toString(), start),
|
||||
"testNewLastIndexOf fails! original : " + a + " seg : " + b + " start : " + start
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue