/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.tools.string; import org.apache.commons.lang.ArrayUtils; public class StringSpliter { /** * 这个对象是为了在复杂的字符串分割过程中,避免在内存中产生过多的String对象,实现节约资源提供性能的目的, * 尤其是在对较长的String对象操作时,效率要高出很多。 * 实现原理是使用了Substring类,由于Substring类只通过简单的int型数字记录分割点的位置,不实际分割字串对象,所以节省系统资源 * * Chart of a String cutter * -----------============------------------ * | | | | * begin keyStr end * */ private Substring keyword; private Substring source; public static final int MODE_FROM_LEFT = 0;// 从左向右查找 public static final int MODE_FROM_RIGHT = 1;// 从右向左查找 private int findMode = MODE_FROM_LEFT; public StringSpliter(Substring source) { this.source = source; this.keyword = null; } // public StringSpliter(Substring source, int begin, int end) { // this.source = source; // this.keyword = source.sub(begin, end); // } public StringSpliter(String source){ this.source = new Substring(source); this.keyword = null; } public Substring getKeyword() { return keyword; } public Substring getSource() { return source; } public void setSource(Substring source) { this.source = source; this.keyword=null; } /** * 将key向两边扩展,如果两边的相邻字符和指定的字符相同的话,将其扩展到key的范围 * @param chars */ public boolean expandKey(char[] chars){ boolean res=expandKeyLeft(chars); if(expandKeyRight(chars)){ res=true; } return res; } /** * 如果左侧字符在指定列表中,则向左扩展key * @param chars * @return */ public boolean expandKeyLeft(char[] chars){ boolean res=false; if(keyword==null)return res; Substring left=getLeft(); while(left.lastCharacter()!=null && ArrayUtils.contains(chars,left.lastCharacter().charValue())){ left.setEnd(left.getEnd()-1); res=true; } if(res)this.keyword=source.subAbsoultOffset(left.getEnd(), keyword.getEnd()); return res; } /** * 如果右侧字符在指定的列表中,则向右扩展key * @param chars * @return */ public boolean expandKeyRight(char[] chars){ boolean res=false; if(keyword==null)return res; Substring right=getRight(); while(right.firstCharacter()!=null && ArrayUtils.contains(chars,right.firstCharacter().charValue())){ right.setStart(right.getStart()+1); res=true; } if(res)this.keyword=source.subAbsoultOffset(keyword.getStart(), right.getStart()); return res; } public boolean expandKeyLeft(int count){ if(source.getStart()>keyword.getStart()-count){//如果key越过souce边界,则返回 return false; } if(keyword.getEnd()<keyword.getStart()-count){//如果key越过key end边界,则返回 return false; } keyword.setStart(keyword.getStart()-count); return true; } public boolean expandKeyRight(int count){ if(source.getEnd()<keyword.getEnd()+count){ return false; } if(keyword.getStart()>keyword.getEnd()+count){ return false; } keyword.setEnd(keyword.getEnd()+count); return true; } /** * 向两端扩张key的范围,直到出现指定的字符才停下(指定字符不含) * @param chars * @return */ public boolean expandKeyUntil(char[] chars){ boolean res=expandKeyLeftUntil(chars); if(expandKeyRightUntil(chars)){ res=true; } return res; } /** * 向左扩张Key的范围,直到出现指定的字符才停下(指定字符不含) * @param chars * @return */ public boolean expandKeyLeftUntil(char[] chars){ boolean res=false; if(keyword==null)return res; Substring left=getLeft(); while(left.lastCharacter()!=null && !ArrayUtils.contains(chars,left.lastCharacter().charValue())){ left.setEnd(left.getEnd()-1); res=true; } if(res)this.keyword=source.subAbsoultOffset(left.getEnd(), keyword.getEnd()); return res; } /** * 向右扩张Key的范围,直到出现指定的字符才停下(指定字符不含) * @param chars * @return */ public boolean expandKeyRightUntil(char[] chars){ boolean res=false; if(keyword==null)return res; Substring right=getRight(); while(right.firstCharacter()!=null && !ArrayUtils.contains(chars,right.firstCharacter().charValue())){ right.setStart(right.getStart()+1); res=true; } if(res)this.keyword=source.subAbsoultOffset(keyword.getStart(), right.getStart()); return res; } /** * 获取左边部分 * @return */ public Substring getLeft() { if (keyword == null) { if (findMode == MODE_FROM_LEFT) { return source; } else { return null; } } else { return source.subAbsoultOffset(source.getStart(), keyword.getStart()); } } /** * 获取右边部分 * * @return */ public Substring getRight() { if (keyword == null) { if (findMode == MODE_FROM_LEFT) { return null; } else { return source; } } else { return source.subAbsoultOffset(keyword.getEnd(), source.getEnd()); } } /** * 得到带key的左边部分 */ public Substring getLeftWithKey() { if (keyword == null) { if (findMode == MODE_FROM_LEFT) { return null; } else { return source; } } else { return source.subAbsoultOffset(source.getStart(), keyword.getEnd()); } } /** * 得到带key的右边部分 */ public Substring getRightWithKey() { if (keyword == null) { if (findMode == MODE_FROM_LEFT) { return null; } else { return source; } } else { return source.subAbsoultOffset(keyword.getStart(), source.getEnd()); } } /** * 设置一个值,查找,如果找到就形成keyStr对象,从而将对象可拆分为三个Substring. * @param str */ public boolean setKey(String str) { if(str==null){ this.keyword = null; return false; } int n=-1; if (findMode == MODE_FROM_RIGHT) { n= source.lastIndexOf(str); } else { n= source.indexOf(str); } if(n>-1){ this.keyword = source.sub(n, n+str.length()); return true; }else{ this.keyword = null; return false; } } public boolean setKey(int ketStart,int keyEnd) { try{ this.keyword=source.sub(ketStart, keyEnd); return true; }catch (IllegalArgumentException e){ return false; } } public boolean setKey(char str) { if(str==0){ this.keyword = null; return false; } int n=-1; if (findMode == MODE_FROM_RIGHT) { n= source.lastIndexOf(str); } else { n= source.indexOf(str); } if(n>-1){ this.keyword = source.sub(n, n+1); return true; }else{ this.keyword = null; return false; } } //目前算法效率不够高,还可以继续优化 public boolean setKeyOfAny(String[] ss) { int find=-1; int length=0; for(String str:ss){ if (findMode == MODE_FROM_RIGHT) { int n= source.lastIndexOf(str); if(n>find || find==-1){ find=n; length=str.length(); } } else { int n= source.indexOf(str); if(n>-1 && (n<find || find==-1)){ find=n; length=str.length(); } } } if(find>-1){ this.keyword = source.sub(find, find+length); }else{ this.keyword = null; } return keyword!=null; } public boolean setKeyOfAny(char[] chars) { int find=-1; for(char c:chars){ if (findMode == MODE_FROM_RIGHT) { int n= source.lastIndexOf(c); if(n>find || find==-1){ find=n; } } else { int n= source.indexOf(c); if(n>-1 && (n<find || find==-1)){ find=n; } } } if(find>-1){ this.keyword = source.sub(find, find+1); }else{ this.keyword = null; } return keyword!=null; } public int getMode() { return findMode; } public void setMode(int mode) { this.findMode = mode; } }