17

我有实现 Set 和 List 的类。程序在 Java6 和 Java7 中运行良好

public class SetList<V> implements Set<V>, List<V>
{
  ....
}

对于 Java 8 ,这不会编译。错误是

java:类 trial.SetList 从 java.util.Set 和 java.util.List 类型继承了 spliterator() 的不相关默认值

java/util/Set.java:394

 ...
@Override
default Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, Spliterator.DISTINCT);
}

java/util/List.java

...
@Override
default Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, Spliterator.ORDERED);
}

这是否意味着我不能拥有在 Java 8 中同时实现 Set 和 List 的类?(看来是时候偿还我们的技术债务了。)

4

3 回答 3

12

虽然一个类同时实现Listand是不寻常的Set,但在某些情况下,aSet也可以支持有点受限的List

就个人而言,我更喜欢asList()在这些情况下声明一个方法,而不是同时实现List两者Set。像这样的东西:

public class SetList<V> implements Set<V> {
    public List<V> asList(){
        // return a list representation of this Set
    }
}

另一方面,如果您已经有一个实现了List和的现有类,Set那么解决问题的最简单方法可能是显式调用其中一个超级spliterator()方法:

public class SetList<V> implements Set<V>, List<V> {
    @Override
    public Spliterator<V> spliterator() {
        return List.super.spliterator();
    }
}
于 2014-03-31T13:17:21.037 回答
8

这是多重继承中导致的钻石问题

“钻石问题”(有时被称为“死亡的致命钻石”)是当两个类 B 和 C 继承自 A,而类 D 继承自 B 和 C 时出现的歧义。如果 A 中有方法B 和 C 已经被覆盖,而 D 没有覆盖它,那么 D 继承了哪个版本的方法:B 的,还是 C 的?

在 Java 中,编译错误可以防止这个问题。为了解决这个你应该实现你的

于 2016-09-17T07:20:01.900 回答
0

就我而言,我在ListSet课堂上使用了多个基础列表和集合。

因为我碰巧已经实现了size()anditerator()方法(使用 Guava Iterators.concat),所以最简单的解决方案是使用Spliterators.spliterator()接受Iteratorand 大小的重载。

/**
 * A custom list container that combines a set of unchangeable items with a list of changeable ones.
 * An iterator {@link #iterator()} is available that will iterate first through the unchangeable
 * items and then through the changeable ones. {@link #size()} is the total combined size and
 * {@link #get(int)} can return either an item from the unchangeable list or the changeable one.
 *
 * @param <E>
 */
class ListSet<E> implements List<E>, Set<E> {
    @NonNull
    private final ImmutableList<E> mConstantItemsList;
    @NonNull
    private final ImmutableSet<E> mConstantItemsSet;
    @NonNull
    private final List<E> mVariableItems;

    ListSet(Set<E> constantItems) {
        mConstantItemsSet = ImmutableSet.copyOf(constantItems);
        mConstantItemsList = ImmutableList.copyOf(constantItems);
        mVariableItems = Lists.newArrayList();
    }

    @NonNull
    @Override
    public Iterator<E> iterator() {
        return Iterators.concat(mConstantItemsList.iterator(), mVariableItems.iterator());
    }

    @Override
    public int size() {
        return mConstantItemsList.size() + mVariableItems.size();
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public Spliterator<E> spliterator() {
        return Spliterators.spliterator(iterator(), size(), Spliterator.ORDERED | Spliterator.DISTINCT);
    }
}


于 2021-05-12T16:36:40.483 回答