Java 查找包含子字符串的Arraylist的所有字符串的有效方法

Java 查找包含子字符串的Arraylist的所有字符串的有效方法,java,regex,string,arraylist,Java,Regex,String,Arraylist,我有一个字符串,比如a=1.1,还有一个arraylist,比如list,它有以下字符串:1.1.1.1,1.1.2.4,1.2,1.3,1.5.1.1 现在,我想从这个arraylist中获取字符串,它的开头包含字符串a=1.1,这意味着a是这些字符串的子字符串,需要从头开始匹配 因此,对于这种情况,答案将是1.1.1.1和1.1.2.4,但不是1.5.1.1,因为这里1.1不是在开头 我知道如何实现这一点,但我认为我的解决方案不够高效,对于大型arraylist,它将需要更多的处理时间 我的

我有一个字符串,比如a=1.1,还有一个arraylist,比如list,它有以下字符串:1.1.1.1,1.1.2.4,1.2,1.3,1.5.1.1

现在,我想从这个arraylist中获取字符串,它的开头包含字符串a=1.1,这意味着a是这些字符串的子字符串,需要从头开始匹配

因此,对于这种情况,答案将是1.1.1.1和1.1.2.4,但不是1.5.1.1,因为这里1.1不是在开头

我知道如何实现这一点,但我认为我的解决方案不够高效,对于大型arraylist,它将需要更多的处理时间

我的做法: 对arraylist运行for循环,对于每个字符串,从开始处以a的长度裁剪字符串,并检查裁剪后的字符串是否等于a

但是,如果我想对一个大型arraylist的几个字符串重复这一点,我认为这不是一个好的解决方案


有什么想法吗?我将非常感谢您的帮助。

这里有一个想法,但我不知道它是否足够有效。以某种方式连接所有元素,以便您可以找出其中的项目: 例如:

{0:1.1.2.4},{1:1.2.1.3}

然后对字符串运行正则表达式查询,返回以{开头,以}结尾,以1.1开头的所有子字符串。您可以定义一个包含索引号的命名组,以便在一次运行中拥有所有索引。

此方法将起作用:

public static List<String> findWithPrefix(List<String> list, String prefix) {
    List<String> result = new ArrayList<>();
    for(String s : list)
        if(s.startsWith(prefix))
            result.add(s);
    return result;
}
如果您可以使用Java 8,它将更短:

public static List<String> findWithPrefixJava8(List<String> list, String prefix) {
    return list.stream()
               .filter(str -> str.startsWith(prefix))
               .collect(Collectors.toList());
}

您可以始终使用String类中的startsWithString方法

e、 g


如果您想浏览列表并提取所有以1.1开头的字符串,那么使用startsWithString subString应该完成您需要的操作。您可以使用Java8 Collection.parallelStream.forEach

另一方面,如果您想进行多个搜索,每次看到哪个字符串以不同的子字符串开始,并以这里的键开始,您可以查看

后缀树将以类似于树的方式索引所有字符串。通过这种方式,您可以从根节点开始搜索树,然后,一旦找到满足条件的节点,您只需继续遍历它的子节点即可获得字符串

                root
              / |  \
             1  2   3
          / |
         .  0
    /   |
   1    2
   |    |
   [1.1] [1.2]
方括号中的值表示找到的子字符串的位置,在您的情况下,子字符串将由整个字符串组成。

嘿,因为您需要一些优化的解决方案,所以可以尝试以下方法:

List<String> result=new ArrayList<String>():
for(String s : list){
 if(s.startsWith("1.1")){
    result.add(s);
 }
}
for(String s : list){
System.out.println(s);
}
在Collections.sortlist的帮助下对列表进行排序; 在二进制搜索的帮助下查找第一个匹配的字符串,并将具有此前缀的字符串标记为已找到。 现在,如果下一个字符串与这个前缀不匹配,这意味着列表的下一个字符串将与这个前缀不匹配,因为我们已经对集合进行了排序 请尝试以下代码:

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class T { 
    static int count=0;     
    public static void main(String[] args) {    
        List<String> list = new ArrayList<String>();

       // for testing purpose only i am making this list and putting this data
        for (int i = 101; i < 501; i++) {
            list.add(i + "");
        }
        boolean matchedSuffix = false;
        String prefix = "30";

        Collections.sort(list);

        int startFrom = T.binarySerchOverList(list, prefix);

        if (startFrom == -1) {
            System.out.println("no data found");
        } else {
                for (int i = startFrom;; i++) {
                String s = list.get(i);
                if (s.startsWith(prefix)) {                     
                    //here you will get matching strings                    
                    System.out.println(s);
                    matchedSuffix = true;
                } else {
                    if (matchedSuffix) {
                        break;
                    }
                }

            }
        }    
    }

    public static int binarySerchOverList(List<String> input, String prefix) {    
        count++;
        System.out.println( "iteration count is "+count);       
        int size = input.size();
        int midpoint = size / 2;
        int startPoint = 0;

        String stringToTest = input.get(midpoint);
        if (stringToTest.startsWith(prefix)) {
            startPoint = midpoint - 1;
            while (true) {

                if (!input.get(startPoint).startsWith(prefix)) {
                    startPoint++;
                    break;
                }
                if (startPoint == 0) {
                    break;
                }   
                startPoint--;
            }   
            return startPoint;
        }

        if (stringToTest.compareTo(prefix) > 0) {
            List<String> sublist = input.subList(0, midpoint);
            return binarySerchOverList(sublist, prefix);
        }

        if (stringToTest.compareTo(prefix) < 0) {    
            if (input.get(input.size() - 1).compareTo(prefix) < 0) {
                return -1;
            }
            List<String> sublist = input.subList(midpoint, input.size());
            return binarySerchOverList(sublist, prefix);
        }    
        return 0;    
    }    
}
如果您对代码有疑问,请询问我它必须是ArrayList吗?能否将字符串像树集一样放入NavigableSet:


可以使用字符串的startsWithString str方法,也可以使用startsWithString s。如果你需要不止一次地发布你的代码,那么将列表排序几乎是绝对值得的。然后你就可以进行二进制搜索了。这听起来比它的价值要麻烦得多。regexp总是要扫描整个字符串,这是我们想要避免的事情。为什么这么说?你是说用正则表达式解决这样的问题?在这种情况下,它只是一个错误的工具。用一个大的列表连接元素并再次扫描整个列表是非常昂贵的!如果您可以对其进行排序,则不需要。当然,这并不是说把regexp弄错有多容易。soz mate,我在发布我的答案之前没有看到你的答案,如果我能使用java 8,那会更好。但是出于可比性的原因,我不得不选择Java7。谢谢,这是一个非常好的主意。但我的实施清单并没有那么大。我以后会用你的方法来处理大型列表。这张图片是什么输入字符串的后缀树?@StefanPochmann:完整的输入字符串将是1.1和1.2。列表中的其他子字符串包括10、1、2和3。您可能希望将s作为参数传递给result.add。还有,为什么不在第一个循环中执行print语句呢?这就是为什么list的值可以在其他地方迭代,即使在不同的类或不同的包中也是如此。剩下要做的就是使用二进制搜索而不是线性搜索来查找第一个元素。
package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class T { 
    static int count=0;     
    public static void main(String[] args) {    
        List<String> list = new ArrayList<String>();

       // for testing purpose only i am making this list and putting this data
        for (int i = 101; i < 501; i++) {
            list.add(i + "");
        }
        boolean matchedSuffix = false;
        String prefix = "30";

        Collections.sort(list);

        int startFrom = T.binarySerchOverList(list, prefix);

        if (startFrom == -1) {
            System.out.println("no data found");
        } else {
                for (int i = startFrom;; i++) {
                String s = list.get(i);
                if (s.startsWith(prefix)) {                     
                    //here you will get matching strings                    
                    System.out.println(s);
                    matchedSuffix = true;
                } else {
                    if (matchedSuffix) {
                        break;
                    }
                }

            }
        }    
    }

    public static int binarySerchOverList(List<String> input, String prefix) {    
        count++;
        System.out.println( "iteration count is "+count);       
        int size = input.size();
        int midpoint = size / 2;
        int startPoint = 0;

        String stringToTest = input.get(midpoint);
        if (stringToTest.startsWith(prefix)) {
            startPoint = midpoint - 1;
            while (true) {

                if (!input.get(startPoint).startsWith(prefix)) {
                    startPoint++;
                    break;
                }
                if (startPoint == 0) {
                    break;
                }   
                startPoint--;
            }   
            return startPoint;
        }

        if (stringToTest.compareTo(prefix) > 0) {
            List<String> sublist = input.subList(0, midpoint);
            return binarySerchOverList(sublist, prefix);
        }

        if (stringToTest.compareTo(prefix) < 0) {    
            if (input.get(input.size() - 1).compareTo(prefix) < 0) {
                return -1;
            }
            List<String> sublist = input.subList(midpoint, input.size());
            return binarySerchOverList(sublist, prefix);
        }    
        return 0;    
    }    
}
TreeSet<String> strings = ...;

Set<String> startWith1_1 = strings.subSet("1.1", "1.2");