【问题标题】:Efficient way of finding all strings of an Arraylist, which contains a substring查找包含子字符串的 Arraylist 的所有字符串的有效方法
【发布时间】:2015-07-16 10:43:39
【问题描述】:

我有一个字符串,比如a="1.1" 和一个数组列表,比如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.11.1.2.4 而不是 1.5.1.1,因为这里 1.1 不是开头。

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

我的方法: 为 arraylist 和每个字符串运行一个 for 循环,从 a 的长度开始裁剪字符串,并检查裁剪的字符串是否与 a 相等。

但是如果我想对一个大数组列表的几个字符串重复这个,我认为这不是一个好的解决方案。

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

【问题讨论】:

  • 你可以使用StringclassstartsWith(String str)方法
  • 您可以改用startsWith(String s)。有一个look
  • 请发布您的代码。
  • 如果您需要多次执行此操作,那么几乎绝对值得对列表进行排序。然后就可以进行二分查找了。

标签: java regex string arraylist


【解决方案1】:

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

{0:1.1.2.4},{1:1.2.1.3},.....

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

【讨论】:

  • 这听起来比它的价值要麻烦得多。正则表达式总是需要扫描整个字符串,这是我们想要避免的。
  • 你为什么这么说?你的意思是使用正则表达式来解决这样的问题?
  • 在这种情况下,这只是错误的工具。对于大列表,连接元素非常昂贵,如果您可以对其进行排序,则无需扫描整个列表(再次!)。当然,这并没有说明弄错正则表达式有多么容易。
【解决方案2】:

此方法可行:

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

【讨论】:

  • soz mate,在发布之前我没有看到你的答案,
  • 如果我可以使用 java 8 会更好。但是出于可比性的原因,我必须使用 java 7。
【解决方案3】:

你总是可以使用 String 类中的 startsWith(String s) 方法。

例如

for(String s : list){
 if(s.startsWith(a)){
    System.out.println(s);
 }
}

【讨论】:

    【解决方案4】:

    如果您想浏览列表并提取所有以1.1 开头的字符串,那么使用startsWith(String subString) 应该可以满足您的需求。你可以使用 Java 8 Collection.parallelStream().forEach...

    另一方面,如果您想要进行多次搜索,每次查看哪个字符串以不同的子字符串开头开头是这里的关键),你可以看看suffix trees

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

                    root
                  / |  \
                 1  2   3
              / |
             .  0
        /   |
       1    2
       |    |
       [1.1] [1.2]
    

    方括号中的值,表示找到的子字符串在哪里,在您的情况下,它将由整个字符串组成。

    【讨论】:

    • 谢谢,这真是个好主意。但我的实施清单并没有那么大。将来我会在大型列表中使用您的方法。
    • 那张图片是什么输入字符串的后缀树?
    • @StefanPochmann:完整的输入字符串为1.11.2。列表中的其他子字符串包括10123
    【解决方案5】:
    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);
    }
    

    【讨论】:

    • 您可能希望将s 作为参数传递给result.add()。另外,为什么不在第一个循环中执行 print 语句?
    • 这就是为什么 list 的值可以在其他地方迭代,即使在不同的类或不同的包中也是如此。
    【解决方案6】:

    嘿,你想要一些优化的解决方案,所以你可以试试这个:

    1. Collections.sort(list); 的帮助下对列表进行排序
    2. 在二分查找的帮助下找到第一个匹配的字符串,并用找到的前缀标记该字符串。
    3. 现在如果下一个字符串与此前缀不匹配,这意味着列表的下一个字符串将不会匹配此前缀,因为我们已经对集合进行了排序

    试试这个代码:

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

    如果您对代码有疑问,请咨询我

    【讨论】:

    • 剩下要做的就是使用二分查找而不是线性查找来查找第一个元素。
    【解决方案7】:

    必须是ArrayList吗?你能把字符串像TreeSet一样放入NavigableSet

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-03
      • 2012-06-28
      • 2015-02-18
      • 2019-02-17
      • 2011-03-11
      相关资源
      最近更新 更多