Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在排序的ArrayList中查找以子字符串开头的元素?_Java_Search_Arraylist - Fatal编程技术网

Java 如何在排序的ArrayList中查找以子字符串开头的元素?

Java 如何在排序的ArrayList中查找以子字符串开头的元素?,java,search,arraylist,Java,Search,Arraylist,我有一个使用java排序的33000个元素的arrayList,我怎么能只列出以子字符串开头的元素呢 例如: 我有一串“空气”。所以我需要每个以“air”开头的单词(“飞机”、“空军”、“航空公司”等等) 有没有一种方法可以在不逐个迭代的情况下执行此操作?因此,如果您有一个排序的数组列表单词,您可以执行以下操作: String prefix = "air"; int start = Collections.binarySearch(words, prefix); // index of pr

我有一个使用java排序的33000个元素的arrayList,我怎么能只列出以子字符串开头的元素呢

例如: 我有一串“空气”。所以我需要每个以“air”开头的单词(“飞机”、“空军”、“航空公司”等等)


有没有一种方法可以在不逐个迭代的情况下执行此操作?

因此,如果您有一个排序的
数组列表
单词
,您可以执行以下操作:

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);