【问题标题】:Creating abstract data type in Java在 Java 中创建抽象数据类型
【发布时间】:2018-04-08 06:27:18
【问题描述】:

我需要创建一个集合,它将保存两个集合的交集。如果其中一个集合中存在的值发生更改,intersectionSet 也应该受到影响。

为测试设置:

Set<Integer> testSet1 = new HashSet<>();
testSet1.add(1);
testSet1.add(2);
testSet1.add(3);

Set<Integer> testSet2 = new HashSet<>();
testSet2.add(2);
testSet2.add(4);

如果我这样实现intersectionSet,即使testSet1或testSet2发生变化也不受影响。

Set<Integer> intersectionSet = new HashSet<>(testSet1);
intersectionSet.removeIf(element -> !testSet2.contains(element));

如果我这样实现,在创建intersectionSet时,testSet1或testSet2会被.removeIf()修改,但这里只是从intersectionSet中删除对值的引用。

Set<Integer> intersectionSet;
intersectionSet = testSet1;
intersectionSet.removeIf(element -> !testSet2.contains(element));

一般来说,intersectionSet 应该只持有对 testSet1 和 testSet2 中适合条件的值的引用。

问题是,我如何实现 intersectionSet 使其依赖于 testSet1 和 testSet2(以及它们的内容)并且不会改变它们。

我需要这样的东西:

System.out.println(testSet1.contains(1)); // print true

IntersectionSet intersectionSet = new IntersectionSet(testSet1, testSet2);

System.out.println(testSet1.contains(1)); // print true
System.out.println(testSet2.contains(4)); // print true
System.out.println(intersectionSet.contains(2)); // print true

testSet1.remove(2);

System.out.println(intersectionSet.contains(2)); // print false

我的代码如下:

interface OMOSetView {
    boolean contains(int element); // test if element is in set

    int[] toArray(); //return copy of elemets from set in array

    OMOSetView copy(); //return copy of set

    int size(); //return size of set

    HashSet<Integer> getSet(); //retunrn set
}

// class which represents common set, defines methods add/remove
class OMOSet implements OMOSetView {
    private HashSet<Integer> omoSet = new HashSet<>();

    public void add(int element) {
        if (!omoSet.contains(element)) {
            omoSet.add(element);
        }
    }

    public void remove(int element) {
        if (omoSet.contains(element)) {
            omoSet.remove(element);
        }
    }

    public boolean contains(int element) {
        return omoSet.contains(element);
    }

    public int[] toArray() {
        int[] array = new int[omoSet.size()];
        int i = 0;
        for (Integer element : omoSet) {
            array[i] = element;
            i++;
        }
        return array;
    }

    public OMOSet copy() {
        OMOSet copySet = new OMOSet();
        for (Integer element : omoSet) {
            copySet.add(element);
        }
        return copySet;
    }

    public int size() {
        return omoSet.size();
    }

    public HashSet<Integer> getSet() {
        return this.omoSet;
    }

}

    // class represents intersectionSet of two sets A and B
class OMOSetIntersection implements OMOSetView {
    private HashSet<Integer> intersectionSet;

    OMOSetIntersection(OMOSetView setA, OMOSetView setB) {
        intersectionSet = setA.getSet();                              // it's not working
        intersectionSet.removeIf(element -> !setB.contains(element)); // it's not working
    }

    public boolean contains(int element) {
        return intersectionSet.contains(element);
    }

    public int[] toArray() {
        int[] array = new int[intersectionSet.size()];
        int i = 0;
        for (Integer element : intersectionSet) {
            array[i] = element;
            i++;
        }
        return array;
    }

    public OMOSet copy() {
        OMOSet copySet = new OMOSet();
        for (Integer element : intersectionSet) {
            copySet.add(element);
        }
        return copySet;
    }

    public int size() {
        return intersectionSet.size();
    }

    public HashSet<Integer> getSet() {
        return intersectionSet;
    }
}

【问题讨论】:

  • ...是吗?这里有问题吗?
  • @LouisWasserman 已编辑。谢谢。

标签: java collections reference hashset


【解决方案1】:

您应该使用实现延迟计算的包装器:这意味着它们不保存实际的交集元素,而是保留对原始集合的引用并根据请求提供交集。

Google Guava 提供了大量用于延迟计算的收集实用程序。在您的情况下,com.google.common.collect.Sets#intersection(Set&lt;E&gt; set1, Set&lt;?&gt; set2) 是一种方法:

Set<Integer> testSet1 = new HashSet<>();
testSet1.add(1);
testSet1.add(2);
testSet1.add(3);

Set<Integer> testSet2 = new HashSet<>();
testSet2.add(2);
testSet2.add(4);

Set<Integer> intersectionSet = Sets.intersection(testSet1, testSet2);

【讨论】:

  • 还有其他解决方案吗?我还必须实现补集(complSet = A \ B)和集合,它只包含原始集合中的偶数,所以我想知道一个更常见的解决方案。这个任务来自我的大学作业,所以不用 Google Guava 也可以解决。
  • 你有两个选择:要么根据我在答案开头的解释自己做,要么选择 Guava 的 collection utils source code
  • 主要思想:你必须提供自己的Set接口实现
  • 我已经这样做了,我遇到的两个问题是:1. IntersectionSet 对更改原始集合之一没有反应,或者 2. 从 IntersectionSet 中删除元素也会影响原始集合之一设置。
  • 我在您的代码中没有看到像 public class IntersectionSet implements Set 这样的自定义类...
猜你喜欢
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多