【问题标题】:Removing common elements between two different Arraylist删除两个不同 Arraylist 之间的公共元素
【发布时间】:2013-04-11 12:54:00
【问题描述】:

我已为此阅读了几篇文章,但没有得到我正在寻找的确切内容。我知道如何为此开发一个复杂的逻辑,这是针对 Android 的,由于可用资源有限,我们不能指望设备上有太多的处理。

我有一个包含五个字段的 bean 类对象的 ArrayList

Java Bean -- MyShares

  1. 文件名
  2. 文件路径
  3. 文件大小
  4. 是共享的
  5. 创作者

我有另一个仅包含文件路径的字符串数组列表。现在我想要的是删除两个数组列表之间的所有公共元素意味着以秒为单位的文件路径数组列表和第一个数组列表对象中的文件路径相似然后我必须从两个数组列表中删除但我不想要一个新的数组列表其中包含不常见的元素。但我只想在没有共同元素的情况下获得我的两个数组列表。

【问题讨论】:

  • 到目前为止你尝试了什么?给我们看。
  • 使用 Set 而不是 List 怎么样?
  • @Achintya Jain okkk 等一下
  • @krishna 但是我的一个数组列表包含一个 bean 对象,它有 5 个字段,我只需要比较一个

标签: java android arraylist


【解决方案1】:

您可以将String 中的Map 用于您的对象类型(我使用Obj 来制作SSCCE)。

假设我们得到一个列表 objects 和一个列表 strings

步骤:

  1. 将所有objects 放在map 中,并将str 变量作为键
  2. 使用map.keySet() 获取所有str 变量
  3. 通过keys.removeAll(strings)获取objects中但不在strings中的所有字符串
  4. 通过strings.removeAll(keys)获取strings中但不在objects中的所有字符串
  5. 获取与剩余keys对应的objects

请注意,在步骤 3 和 4 中您需要小心,因为您需要备份其中一个集合。

import java.util.*;

public class Test { 
    public static void main(String[] args) throws Exception {
        new Test();
    }

    public Test() {
        List<Obj> objects = new ArrayList<>();
        objects.add(new Obj("a"));
        objects.add(new Obj("b"));
        objects.add(new Obj("c"));

        List<String> strings = new ArrayList<>();
        strings.add("a");
        strings.add("d");
        strings.add("e");

        remove(objects, strings);

        System.out.println(objects);
        System.out.println(strings);
    }

    public void remove(List<Obj> objects, List<String> strings) {
        Map<String, Obj> map = new HashMap<>();
        for (Obj object : objects) {
            map.put(object.str, object);
        }

        Set<String> keys = map.keySet();
        List<String> oldStrings = new ArrayList<>(strings);

        strings.removeAll(keys);
        keys.removeAll(oldStrings);

        objects.clear();
        for (String key: keys) {
            objects.add(map.get(key));
        }       
    }

    public class Obj {  
        public String str;
        public Obj(String str) {
            this.str = str;
        }
        @Override
        public String toString() {
            return str;
        }       
    }
}

打印:

[b, c]
[d, e]

【讨论】:

    【解决方案2】:

    粗略的 Java 代码:

    HashSet<String> commonKeys = new HashSet();
    for (Share share : shares) {
        commonKeys.add(share.filePath);
    }
    commonKeys.retainAll(filePaths);
    for (Iterator<Share> it = shares.iterator(); it.hasNext(); ) {
        Share share = it.next();
        if (commonKeys.contains(share.filePath)) {
            it.remove();
        }
    }
    filePaths.removeAll(commonKeys);
    

    这不会是O(N),因为ArrayList 上的remove 很昂贵。要获得O(N) 行为,您需要创建新的ArrayList 实例,或者将您不想删除的元素添加到临时列表中,然后clear() 并将它们添加回原始列表中。

    【讨论】:

      【解决方案3】:

      我会为你提供一些线索

      假设您有两个列表,一个用于 bean 对象,即 myBeans,另一个用于文件路径,即 filePaths

      List<MyBean> beansToRemove = new ArrayList<MyBean>();
      List<FilePath> filePathsToRemove = new ArrayList<FilePath>();
      
      for(Bean myBean : myBeans) {
          for(FilePath filePath : filePaths) {
              if(myBean.getfilePath.equals(filePath.getFilePath())) {
                  beansToRemove.add(myBean);
                  filePathsToRemove.add(filePath);
              }
          }
      }
      
      //Now remove filePaths and beans if any
      
      for(Bean myBean : beansToRemove) {
          myBeans.remove(myBean);
      }
      
      for(FilePath filePath : filePathsToRemove) {
          filePaths.remove(filePath);
      }
      

      这只是一个让你清楚要做什么的流程;您可以根据需要进一步自定义。

      【讨论】:

        【解决方案4】:

        您可以使用外循环扫描 Bean 对象,使用内循环扫描文件路径。

        伪代码:

        for (Bean i in beans) {
            for (String p in paths) {
                if (i.path.equals(p)) {
                    beansToRemove.add(i);
                    pathsToRemove.add(p);
                }
            }
        }
        beans.removeAll(beansToRemove);
        paths.removeAll(pathsToRemove);
        

        由于原始数组仍然存在,我不确定我用于跟踪已删除数组列表的额外数组列表是否违反您的问题。 如果您对路径上的两个数组进行预排序并跟踪每个区域中的位置(不是详尽搜索),您可以将其从 n2 改进为 nlgn

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多