提示四十七:Stream要优先用Collection作为返回类型。
-
Stream
虽然有一个符合Iterable
接口(Iterator<T> iterator();)可以用, 但是Stream
本身却没有继承Interable
接口. -
Collection
接口是Iterable
的子类型, 还有一个stream
方法, 所以Collection
或其一个合适的子类型, 通常是返回序列的公有方法返回值的最好选择。 - 不要把很大的序列放在内存中,比如"幂集"的实现:
public class PowerSet {
public static final <E> Collection<Set<E>> of(Set<E> s) {
List<E> src = new ArrayList<>(s);
if (src.size() > 30) throw new IllegalArgumentException("Set too big " + s);
return new AbstractList<Set<E>>() {
@Override
public int size() {
return 1 << src.size(); // 2 to the power srcSize
}
@Override
public boolean contains(Object o) {
return o instanceof Set && src.containsAll((Set) o);
}
@Override
public Set<E> get(int index) {
Set<E> result = new HashSet<>();
for (int i = 0; index != 0; i++, index >>= 1) {
if ((index & 1) == 1) {
result.add(src.get(i));
}
}
return result;
}
};
}
}
这里我看了很久,size和contains方法比较简单,关键是get方法。但看代码不是很好想,但是用数学归纳法就比较简单了。如果一个n个元素的集合set和对应的幂集powerSet已经都给出来了,那么多加一个元素以后,他的幂集就会从2的n次方个元素变成2的n+1次方,即两个2的n次方,那么用是否包含第n+1个元素来划分,则前2的n次方个元素就是原来的幂集powerSet,后面2的n次方个元素就是在前面的基础上都加上新的元素即可。所以对所有大于2的n次方的序号i,都有新幂集powerSet'包含第n+1这个元素。用这个思想就能看懂这段代码了。
这一章主要考虑的是方法的返回值要尽量具有普适性(精确),同理,方法的入参要尽可能的模糊,这样方便所有想用这个方法的人来使用。和本书中其他地方一样,作者的思考都站在一个比较高的层次,试图提供一个尽可能普遍的接口。而我们平时开发代码的时候其实一般都是为了某些逻辑而专门定制的代码,所以我们的系统中充满专门为了某一功能写死的代码。各有利弊吧,但是尽可能写出能够复用的代码应该是我们的追求。
网友评论