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

问题描述 投票:0回答:3

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

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

对于 Java 8,这无法编译。错误是

java:类 Trials.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 的类? (看来是时候偿还我们的技术债务了。)

java java-8 technical-debt
3个回答
12
投票

虽然一个类同时实现

List
Set
的情况并不常见,但在某些情况下,
Set
也可以支持某种程度有限的
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();
    }
}

11
投票

这是多重继承发生的钻石问题

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

在Java中,编译错误可以防止这个问题。要解决此问题,您应该提供自己的实现。


0
投票

就我而言,我在

ListSet
类中使用多个基础列表和集合。

由于我碰巧已经实现了

size()
iterator()
方法(使用 Guava
Iterators.concat
),最简单的解决方案是使用
Spliterators.spliterator()
重载接受
Iterator
和大小。

/**
 * 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);
    }
}


© www.soinside.com 2019 - 2024. All rights reserved.