2016-11-19 79 views
-2

我有一个大的ArrayList包含字符串。我想根据元素符合的条件来分割它。例如,如果ArrayList包含String,则它可以是字符串长度。什么是最有效的(而不是最简单的)方法呢?根据条件拆分1 ArrayList为多个1

['a', 'bc', 'defe', 'dsa', 'bb'] 

后会导致到:

['a'], ['bc', 'bb'], ['dsa'], ['defe'] 
+0

没有接近指定条件:有没有可能的优化,你必须用暴力解决。您可以稍微优化各自的数据结构,但匹配本身无法在不知道它完成的属性的情况下进行优化。 – Paul

+0

这是什么情况?为什么'bc'和'bb'分组在一起,但'dsa'和'defe'不是? – SergeyB

+0

@ike_love它遵循问题文本中给出的示例:它们按字符串*长度*进行分组。 – Andreas

回答

1

最有效的方法就是重复原始列表只有一次。你做什么是你创造桶和添加到这些桶。

public class Q1 {  
    public static void main(String[] args) { 
     String[] original = {"a","bc","defe","dsa","bb"}; 

     List<String> originalValues = new ArrayList<String>(Arrays.asList(original)); 
     Map<Integer, List<String>> orderedValues = new HashMap<Integer, List<String>>(); 

     Iterator<String> it = originalValues.iterator(); 
     while (it.hasNext()) { 
      String currentElement = it.next(); 
      int length = currentElement.length(); 
      if(!orderedValues.containsKey(length)) { 
       orderedValues.put(length, new ArrayList<String>()); 
      } 
      orderedValues.get(length).add(currentElement); 
     } 
     System.out.println(orderedValues.values()); 
    } 
} 

你也许会使用数组,而不是一个Map的数组,并使用字符串作为索引到阵列位置的大小,但你需要从哪里看出来的情况下,你不没有一定的长度的字符串。想象一下你在原始列表中只有一个字符串的情况,但它有100个字符。你将不得不在位置阵列中的99个空位置和一个串100

+0

在Java 8中,您可以用'computeIfAbsent(length,ArrayList :: new)'替换'get(length)',消除'if'语句。 ---另外,为什么你使用Iterator' while'循环而不是简单的增强'for'循环? ---合并,将你的循环减少到'for(String value:originalValues){orderedValues.computeIfAbsent(value.length(),ArrayList :: new).add(value); }' – Andreas

+0

我试图让它更具普遍性和兼容性,但是如果他在Java 8中实现,评论中的提示将会很有帮助,谢谢! – palako

2

这很容易,公平高效的使用Java 8流做到这一点:如果你用这个输入运行

Collection<List<String>> output = input.stream() 
             .collect(Collectors.groupingBy(String::length)) 
             .values(); 

List<String> input = Arrays.asList("a", "bc", "defe", "dsa", "bb"); 

你会得到这样的输出:

[[a], [bc, bb], [dsa], [defe]] 

非流版本会做同样的东西,即构建一个Map<K, List<V>>,其中V是您的值类型(例如, String),K是分组值的类型(例如Integer,长度为,长度为)。

自己这样做(如answer by palako中所示)在运行时可能会稍微有效一些,但可能无法以任何方式进行处理。

与Java 8入住,这将是这样的:

Map<Integer, List<String>> map = new HashMap<>(); 
for (String value : input) 
    map.computeIfAbsent(value.length(), ArrayList::new).add(value); 
Collection<List<String>> output = map.values(); 

对于早期版本的Java,您不能使用computeIfAbsent(),所以:

Map<Integer, List<String>> map = new HashMap<Integer, List<String>>(); 
for (String value : input) { 
    Integer length = Integer.valueOf(value.length()); // box only once 
    List<String> list = map.get(length); 
    if (list == null) 
     map.put(length, list = new ArrayList<String>()); 
    list.add(value); 
} 
Collection<List<String>> output = map.values();