Java 如何在排序的ArrayList中查找以子字符串开头的元素?
我有一个使用java排序的33000个元素的arrayList,我怎么能只列出以子字符串开头的元素呢 例如: 我有一串“空气”。所以我需要每个以“air”开头的单词(“飞机”、“空军”、“航空公司”等等)Java 如何在排序的ArrayList中查找以子字符串开头的元素?,java,search,arraylist,Java,Search,Arraylist,我有一个使用java排序的33000个元素的arrayList,我怎么能只列出以子字符串开头的元素呢 例如: 我有一串“空气”。所以我需要每个以“air”开头的单词(“飞机”、“空军”、“航空公司”等等) 有没有一种方法可以在不逐个迭代的情况下执行此操作?因此,如果您有一个排序的数组列表单词,您可以执行以下操作: String prefix = "air"; int start = Collections.binarySearch(words, prefix); // index of pr
有没有一种方法可以在不逐个迭代的情况下执行此操作?因此,如果您有一个排序的
数组列表
单词
,您可以执行以下操作:
String prefix = "air";
int start = Collections.binarySearch(words, prefix);
// index of prefix OR -(insertion point) - 1
if (start < 0) // prefix is not contained as a whole word
start = -start - 1;
int end = start;
while (end < words.size() && words.get(end).startsWith(prefix))
end++;
List<String> prefixWords = words.subList(start, end);
String prefix=“air”;
int start=Collections.binarySearch(单词、前缀);
//前缀或-(插入点)-1的索引
if(start<0)//前缀未包含为一个完整的单词
start=-start-1;
int end=开始;
while(end
二进制搜索是
O(log(N))
,切片是O(K)
,其中K
是子列表的长度(“air”前缀词的数量)。因此,这应该比在列表上迭代要好得多,至少在不同的前缀上迭代(最坏的情况是所有单词都以前缀开头)。如果您不知道之前以“air”开头的元素数,您的搜索顺序将为O(n)。没有暴力方法或平衡树搜索可以在不到O(n)的时间内实现这一点。二进制搜索将是第一个goto
public static int binarySearch(ArrayList<String> sortedArray,String find){
int lowerBound=0;
int upperBound=sortedArray.size()-1;
while(true){
int midIndex=lowerBound+((upperBound-lowerBound)/2);
String curr=sortedArray.get(midIndex);
if(upperBound<lowerBound){
System.out.println("word not found");
return -1;
}
if (curr.equals(find))
return midIndex;
if(curr.compareTo(find)>0)
upperBound=midIndex-1;
if(curr.compareTo(find)<0)
lowerBound=midIndex+1;
}
}
publicstaticintbinarysearch(arraylistsortedarray,stringfind){
int lowerBound=0;
int upperBound=sortedArray.size()-1;
while(true){
int midIndex=下界+((上界下界)/2);
字符串curr=sortedArray.get(midIndex);
如果(上限0)
上限=midIndex-1;
如果(curr.compareTo(find)=0)leftIndex--;
如果((rightIndex+1)=sortedArray.size())&&(leftIndexstartingWith.length()){
isLeft=sortedArray.get(leftIndex).substring(0,startingWith.length()).equals(startingWith);
}else isLeft=false;
if(sortedArray.get(rightIndex).length()>startingWith.length()){
isRight=sortedArray.get(rightIndex).substring(0,startingWith.length()).equals(startingWith);
}否则isRight=false;
if(!isLeft&&!isRight)返回结果;
if(isRight)result.add(sortedArray.get(rightIndex));
if(isLeft)result.add(sortedArray.get(leftIndex));
}
}
怎么样
List List=Arrays.asList(“飞机”、“空军”、“航空公司”、“等等”);
List prefixWords=List.stream()
.filter(word->word.startsWith(“空气”))
.collect(Collectors.toList());
前缀words.forEach(System.out::println);
是的,有多种方法。到目前为止,您尝试了什么?如果列表没有排序,那么它将涉及对整个列表进行迭代!For循环使用正则表达式模式,但我在另一个循环中使用它。对每个循环进行大搜索也是如此……数组列表被排序,然后二进制搜索前缀的插入索引,然后从那里开始。什么是结束?是我的arrayList的结束索引?更新了它。end
是子列表的结束索引(独占)。这是java 8最简单的解决方案。
public static ArrayList<String> makeList(ArrayList<String> sortedArray,String startingWith){
ArrayList<String> result=new ArrayList<>();
ArrayList<String> temp=new ArrayList<>(sortedArray.size());
for(int i=0;i<sortedArray.size();i++){
temp.add(" ");
}
//copy sortedArray to temp
for(String s: sortedArray){
if(s.length()>startingWith.length()) {
temp.set(sortedArray.indexOf(s), s.substring(0, startingWith.length()));
} else temp.set(sortedArray.indexOf(s),s);
}
int index=binarySearch(temp,startingWith);
result.add(sortedArray.get(index));
int leftIndex=index;
int rightIndex=index;
while(true){
//if left and right index dont go out of bounds cont. iterating
if ((leftIndex - 1) >= 0) leftIndex--;
if ((rightIndex + 1) < sortedArray.size()) rightIndex++;
//if left and right index are at end of list return
if( (rightIndex>=sortedArray.size()) && (leftIndex<0) ) return result;
boolean isLeft;
boolean isRight;
if( sortedArray.get(leftIndex).length()>startingWith.length() ) {
isLeft = sortedArray.get(leftIndex).substring(0,startingWith.length()).equals(startingWith);
}else isLeft=false;
if( sortedArray.get(rightIndex).length()>startingWith.length() ) {
isRight = sortedArray.get(rightIndex).substring(0,startingWith.length()).equals(startingWith);
}else isRight=false;
if(!isLeft && !isRight) return result;
if( isRight ) result.add(sortedArray.get(rightIndex));
if( isLeft ) result.add(sortedArray.get(leftIndex));
}
}
List<String> list = Arrays.asList("airplane", "airforce", "airline", "etc.");
List<String> prefixWords = list.stream()
.filter(word -> word.startsWith("air"))
.collect(Collectors.toList());
prefixWords.forEach(System.out::println);