如何将Set<Set>转换为ArrayList<ArrayList>

3

如何将Set<<Set<String>>变量的所有元素添加到ArrayList<<ArrayList<String>>中?当然,我知道天真的做法是直接添加它们。

 private static ArrayList<ArrayList<String>> groupAnagrams(ArrayList<String> words){
              ArrayList<ArrayList<String>> groupedAnagrams = new ArrayList<>();
              AbstractMap<String, String> sortedWords = new HashMap<>();
              Set<Set<String>> sameAnagramsSet = new HashSet<>();
              for(String word : words){
                  char[] wordToSort = word.toCharArray();
                  Arrays.sort(wordToSort);
                  sortedWords.put(word, new String(wordToSort));
              }
              for(Map.Entry<String, String> entry: sortedWords.entrySet() ){
                  Set<String> sameAnagrams = new HashSet<>();
                  sameAnagrams.add(entry.getKey());
                  for(Map.Entry<String, String> toCompare : sortedWords.entrySet()){
                      if(entry.getValue().equals(toCompare.getValue())){
                          sameAnagrams.add(toCompare.getKey());
                      }
                  }
                  if(sameAnagrams.size()>0){
                      sameAnagramsSet.add(sameAnagrams);
                  }
              }

            //-->this line does not work!  return new ArrayList<ArrayList<String>>(sameAnagramsSet);

          }

1
你为什么认为“天真”的方法只是简单地将它们相加是不可接受的? - Benjamin Gruenbaum
@Benjamin Gruenbaum 我想应该有更好的方法,特别是随着Java 8的出现。 - ShahrukhKhan
2个回答

6

在Java 8中,您可以做到:

return sameAnagramsSet.stream()
       .map(ArrayList::new)
       .collect(toList());

尽管它返回一个 List<ArrayList<String>>,但它实际上会做以下几件事情:
  • .stream() 返回一个 Stream<Set<String>>
  • .map(ArrayList::new) 相当于 .map(set -> new ArrayList(set)),它基本上是用一个数组列表替换每个集合
  • collect(toList()) 将所有新创建的列表放入一个列表中

我非常喜欢一个好的Java 8答案。你能解释一下这段代码吗?因为我想很多人(包括我自己)还不太了解Java 8。 - christopher
@assylias 这就是我在寻找的东西;能否解释一下它的作用? - ShahrukhKhan
@assylias 我不明白。我知道 cons 运算符可以分割列表(就像在 OCaml 中一样),但我不知道你在做什么。 - ShahrukhKhan

1

由于您想将每个元素从Set转换为ArrayList,我认为您至少需要使用显式循环来完成这一点(除非您使用Java 8或第三方库):

Set<Set<String>> data = . . .

ArrayList<List<String>> transformed = new ArrayList<List<String>>();
for (Set<String> item : data) {
    transformed.add(new ArrayList<String>(item));
}

注意,我将转换后的列表类型从ArrayList<ArrayList<String>>更改为ArrayList<List<String>>。通常最好使用接口编程,但如果您真的需要一个必须包含特定ArrayList实例的列表,则可以将其切换回去。

我试图避免那样做,我已经明白了这一点,但我想我可以使用Java 8的函数式编程技巧来实现它。 - ShahrukhKhan
OP想要一个ArrayList<ArrayList>,但是一个ArrayList<List>并不相同。 - Dawood ibn Kareem
@DavidWallace - 不,我想不是。对于OP来说似乎并没有太大的区别,因为他显然不想使用这种方法。 - Ted Hopp
是的,但这个答案对于那些仍在使用Java 6或7的人或者更喜欢易于阅读和维护的代码的人很有用。我发现Java 8的答案更难理解,所以作为一名专业程序员,我总是更愿意使用像这样的东西。 - Dawood ibn Kareem
@DavidWallace - 很好的观点。我保留了更改的类型,但添加了一条说明,解释为什么以及如果会创建问题应该怎么做。 - Ted Hopp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接