前几天朋友丢给我这么一道编码题,问我有没有什么想法,我当时第一想法是这道题是不是leetcode那种,这货不会是要在我这装逼炫耀吧,那就尴尬了,作为一个还没深入接触过leetcode的程序员(ps:实在惭愧),怎么可能短时间内把既准确又高效的代码甩给他,并当面给他重重一击呢。哈哈哈,开个玩笑,言归正传。
说起这种分割字符串的问题,我最先想到了学生时代接触到的游标概念,所谓游标,其实就是一个从某一端向另一端依次遍历的指针,所以我在想,用游标是不是可以作为这道题的一种解决策略呢。 基于以上想法,快速梳理一下,要达到目的必须注意以下几个关键点:
话不多说直接上代码(以下代码可能有的bug点:特殊字符、null指针等,目前均尚不考虑)。
public class SplitDemo { public List<String> split(String str, String reg) { List<String> result = new ArrayList<>(); Character[] strArr = toCharacterArray(str); Character[] regArr = toCharacterArray(reg); //游标逻辑 for (int i = 0; i < strArr.length; i++) { //标识多字符是否完全匹配 boolean flag = false; for (int j = 0; j < regArr.length; j++) { flag = regArr[j].equals(strArr[i + j]); if (!flag) { break; } } if (!flag) { continue; } //特殊null值赋值 for (int j = 0; j < regArr.length; j++) { strArr[i + j] = null; } } //结果集封装 String item = ""; for (Character character : strArr) { if (null != character) { item = item + character; } else { if (!"".equals(item)) { result.add(item); item = ""; } } } if (!"".equals(item)) { result.add(item); } return result; } /** 将字符串转为字符包装类数组 */ private Character[] toCharacterArray(String str) { Character[] result = new Character[str.length()]; for (int i = 0; i < result.length; i++) { result[i] = str.charAt(i); } return result; } } 复制代码
测试方法
public static void main(String[] args) { List<String> result = new SplitDemo().split("asasdecdsdxa", "sd"); for (String str : result) { System.out.println(str); } } 复制代码
输出结果
初步完成,但感觉有些繁琐,贴给朋友交流之后,有了另外的处理方法。直接上朋友的代码截图。
这段代码有几个主要的点:
整体逻辑非常清晰,而且代码量更少,初步判断效率更高,这里我不免对String类中的indexOf(String str, int fromIndex)方法充满了好奇,下面让我们追一下JDK源码(版本为JDK8)。
/** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. * * <p>The returned index is the smallest value <i>k</i> for which: * <blockquote><pre> * <i>k</i> >= fromIndex {@code &&} this.startsWith(str, <i>k</i>) * </pre></blockquote> * If no such value of <i>k</i> exists, then {@code -1} is returned. * * @param str the substring to search for. * @param fromIndex the index from which to start the search. * @return the index of the first occurrence of the specified substring, * starting at the specified index, * or {@code -1} if there is no such occurrence. */ public int indexOf(String str, int fromIndex) { return indexOf(value, 0, value.length, str.value, 0, str.value.length, fromIndex); } /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * @param source the characters being searched. * @param sourceOffset offset of the source string. * @param sourceCount count of the source string. * @param target the characters being searched for. * @param targetOffset offset of the target string. * @param targetCount count of the target string. * @param fromIndex the index to begin searching from. */ static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { while (++i <= max && source[i] != first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; } 复制代码
可以看到,其在内部调用了静态方法indexOf(char[] source, int sourceOffset, int sourceCount,char[] target, int targetOffset, int targetCount,int fromIndex),传入参数从左往右依次可以理解为源字符数组(标题中的第一个字符串),源字符数组偏移量(内部调用时默认传入0),源字符数组长度,要查找的字符数组(标题中的第二个字符串),要查找的字符数组偏移量(依旧是0),要查找的字符数组长度,以及初始匹配位置的下标。
进到方法内部,可以看到大体的流程是:
究其内部原理,实际上跟作者一开始的游标方案有异曲同工之处,但更为精妙,尤其是流程控制语句、临界值运用都非常精湛,值得学习!
以上就是本次分享的全部内容啦,有不对的地方欢迎同学们指正!