【问题标题】:How to flatten a list containing both strings and lists-of-strings?如何展平包含字符串和字符串列表的列表?
【发布时间】:2021-02-27 13:41:22
【问题描述】:

如何最好地将包含ArrayList<String>String 对象的ArrayList<Object> 扁平化为扁平化ArrayList<String>

示例

输入:[item1, item2, item3, [item4a, item4b, item4c]]

预期输出:[item1, item2, item3, item4a, item4b, item4c]

创建虚拟示例的代码:

ArrayList<Object> objectList = new ArrayList<Object>();
objectList.add("item1");
objectList.add("item2");
objectList.add("item3");

ArrayList<String> subList = new ArrayList<String>();
subList.add("item4a");
subList.add("item4b");
subList.add("item4c");

objectList.add(subList);

(不)工作解决方案

private ArrayList<String> flattenList(ArrayList<Object> objectList) {
    ArrayList<String> flatLst = new ArrayList<String>();
    
    for (Object item :  objectList) {
        if (item.getClass() == ArrayList.class) {
            System.out.println(item);
            for (Object s : item) {
                flatLst.add(String.valueOf(s));
            }
        } else if (item.getClass() == String.class) {
            flatLst.add(String.valueOf(item));
        }
    }
    return flatLst;
}

这给出了以下错误。

|               for (Object s : item) {
for-each not applicable to expression type
  required: array or java.lang.Iterable
  found:    java.lang.Object

问题:如何解决这个问题?或者更好的是,有什么更清洁的方法来解决这个问题?

【问题讨论】:

    标签: java list arraylist flatten


    【解决方案1】:

    使用stream API

    ArrayList<Object> objectList = new ArrayList<Object>();
    objectList.add("item1");
    objectList.add("item2");
    objectList.add("item3");
    
    ArrayList<String> subList = new ArrayList<String>();
    subList.add("item4a");
    subList.add("item4b");
    subList.add("item4c");
    
    objectList.add(subList);
    List<Object> flat = objectList.stream()
                                  .map(obj -> (obj instanceof List) ? (List<Object>) obj : List.of(obj))
                                  .flatMap(list -> list.stream())
                                  .collect(Collectors.toList());
    System.out.println(flat);
    

    上面的代码打印...

    [item1, item2, item3, item4a, item4b, item4c]
    

    编辑

    根据要求。 List&lt;String&gt; 而不是 List&lt;Object&gt;

    List<String> flat = objectList.stream()
                                  .map(obj -> (obj instanceof List) ? (List<Object>) obj : List.of(obj))
                                  .flatMap(list -> list.stream())
                                  .map(obj -> String.valueOf(obj))
                                  .collect(Collectors.toList());
    

    【讨论】:

    • 这太好了,谢谢。如何让它返回 List&lt;String&gt; 而不是 List&lt;Object&gt;
    【解决方案2】:

    如果您必须使用循环来做同样的事情,这是另一种做同样事情的方法。如果你可以使用 java8 比YCF_L 的解决方案更好。

    public static ArrayList<String> flattenList(ArrayList<Object> objectList) {
            ArrayList<String> flatLst = new ArrayList<String>();
            
            for (Object item :  objectList) {
                if (item instanceof List) {
                    System.out.println(item);
                    for (Object s : (List)item) {
                        flatLst.add(String.valueOf(s));
                    }
                } else if (item instanceof String ) {
                    flatLst.add(String.valueOf(item));
                }
            }
            return flatLst;
        }
    

    【讨论】:

      【解决方案3】:

      你必须通过像这样转换项目来帮助编译器:

      for (Object s : (List) item) {
      

      或者如果你想要一个优雅的解决方案,你可以像这样使用流:

      private ArrayList<String> flattenList(ArrayList<Object> objectList) {
          return objectList.stream()
                  .flatMap(this::extract)
                  .collect(Collectors.toCollection(ArrayList::new));
      
      }
      
      private Stream<String> extract(Object item) {
          if (item.getClass() == ArrayList.class) {
              return ((List<String>) item).stream();
          } else if (item.getClass() == String.class) {
              return Stream.of((String) item);
          }
          return Stream.empty();
      }
      

      【讨论】:

      • 谢谢!但是我收到错误non-static variable this cannot be referenced from a static context
      • 你是什么意思@Andy?哪种解决方案会导致此问题?
      • 我不太确定这里的确切问题是什么,当我尝试编译时会收到上述错误。谢谢你的帮助!我因简洁而授予@Abra
      【解决方案4】:

      For-each 循环需要数组或Iterable 的实例作为其右手操作数。 item的类型是Object,所以需要先强制转换。

      if (item.getClass() == ArrayList.class) {
              ArrayList list = (ArrayList) item;
              for (Object s : list) {
                  flatLst.add(String.valueOf(s));
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-24
        • 2018-12-21
        • 2013-07-25
        • 1970-01-01
        • 1970-01-01
        • 2019-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多