首页 > 解决方案 > 流的奇怪错误

问题描述

所以我创建了自己的 Set,它只是一个常规的集合,但有额外的功能(例如我的集合只存储绝对值)。

这是我的代码:

import java.util.*;

public class SortedByAbsoluteValueIntegerSet<E> extends HashSet<E> {

private Set<Integer> mySet;

public SortedByAbsoluteValueIntegerSet() {
    mySet = new HashSet<Integer>();
}

@Override
public int size() {
    return mySet.size();
}
@Override
public boolean add(E e){
    return mySet.add(Math.abs((Integer) e));
}


@Override
public boolean remove(Object o) {
    return mySet.remove(o);
}

@Override
public boolean contains(Object o){
    return mySet.contains(o);
}

@Override
public boolean addAll(Collection<? extends E> c) {
    List<Integer> myList = new ArrayList<>();
    for (Object e: c) {
        myList.add(Math.abs((Integer) e));
    }
    return mySet.addAll(myList);
}

@Override
public String toString(){
    return mySet.toString();
}

}

我在 JUnit 中有一个测试用例,但失败了。因为我的代码有问题。出于演示目的,为了更好地解释我的问题,我创建了两个函数,它们很好地显示了问题。

这是问题所在:

public static void testSortedByAbsoluteValueIntegerSet() {
    Set<Integer> set1 = new SortedByAbsoluteValueIntegerSet();
    Set<Integer> set2 = new HashSet<>();
    set1.add(5);
    set1.add(3);
    set2.add(5);
    set2.add(3);
    String x = toString(set1); //x is  ""
    String t = toString(set2); //t is "3 5"
}

public static String toString(final Collection<Integer> collection) {
    return String.join(" ", collection.stream()
            .map(i -> Integer.toString(i))
            .toArray(String[]::new));
}

所以问题出现在这一行:

String x = toString(set1); //x is always an empty string
String t = toString(set2); //t works correctly

当我通过调试器时,我看到 String x 始终是一个空字符串,而 String t 可以正常工作。顺便说一句,set1 是我创建的集合的表示,而 set2 只是一个常规的哈希集。

问题是:我怎样才能修复我的 SortedByAbsoluteValueIntegerSet 类,以便 toString() 方法也适用于我自己创建的集合。

PS我是新来的流,我真的不明白这个问题,为什么会发生。

标签: javajunitsetjava-stream

解决方案


这是因为您正在扩展 HashSet,但也使用了内部 Set。

添加时,您将添加到内部 Set 但使用 collection.stream() 时,它会调用继承的 HashSet (为空)。

我相信对你来说最简单的方法是删除内部的“mySet”并在覆盖的方法中调用继承的方法。

例如,您的 add 方法将是

@Override
public boolean add(E e){
    return super.add(Math.abs((Integer) e));
}

(然后您不需要覆盖 toString 或拆分器的大小、删除、包含)

完整示例:

import java.util.*;

public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {


    @Override
    public boolean add(Integer e){
        return super.add(Math.abs(e));
    }

    @Override
    public boolean addAll(Collection<? extends Integer> c) {
        List<Integer> myList = new ArrayList<>();
        for (Integer e: c) {
            myList.add(Math.abs(e));
        }
        return super.addAll(myList);
    }

}

推荐阅读