我目前正在重新发现Java(最近使用Ruby),我喜欢编译所有内容的编译时间。它使重构变得如此简单。但是,我错过了使用类型来快速松散地进行each
循环。这是我最糟糕的代码。
这是否尽可能短?我有一个名为looperTracks
的集合,其中包含实现Looper
的实例。我不想修改该集合,但我想遍历其成员加上this
(也实现Looper
)。
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks.length + 1);
for (LooperTrack track : looperTracks) {
allLoopers.add(track);
}
allLoopers.add(this);
for (Looper looper : allLoopers) {
// Finally! I have a looper
我特别关注从1.5开始我可能错过的Java新功能。对于这个问题,我不询问JRuby还是Groovy虽然我知道他们会为此工作。
编辑:抱歉(Ruby太多了!)...... looperTracks
类型为LooperTrack[]
,LooperTrack
实现Looper
。
答案 0 :(得分:8)
您至少可以使用以下事实:您可以使用另一个作为基本值构建一个集合。根据{{3}}:
按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。 ArrayList实例的初始容量为指定集合大小的110%。
这意味着this
可能无需进行任何调整大小。
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
for (Looper looper : allLoopers) {
// Finally! I have a looper
答案 1 :(得分:7)
至少有两种可能的缩写代码的内置方法:
您可以使用Collection.addAll(Collection)将作为参数传递的集合中的每个元素追加到集合的末尾。:
List<Looper> allLoopers = new ArrayList<Looper>();
...
allLoopers.addAll(looperTracks);
allLoopers.add(this);
for(Looper looper : allLoopers) {
...
}
或者您可以使用将集合作为参数的构造函数:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
由于问题的更改:使用java.util.Arrays可以轻松地将所有数组转换为集合。
List<Looper> someLooperTracks = Arrays.asList(looperTracks).
这会将数组包装在固定大小列表中。
答案 2 :(得分:6)
我认为你不能把它缩短......
for (Looper looper : new ArrayList<Looper>(looperTracks){{ add(EnclosingClass.this); }}) {
// Finally! I have all loopers
}
答案 3 :(得分:4)
Guava让这很简单:
for (Looper looper : ObjectArrays.concat(looperTracks, this)) {}
Here是方法ObjectArrays#concat
的文档。
答案 4 :(得分:2)
我刚刚实施了 Iterator Iterable (它由Guava {{1}以更强大/经过测试/审核的方式实施}):
Iterables.concat(Iterable...)
使用它,您的代码变为:
// make a concatenation of iterables
public static <T> Iterable<T> $(final Iterable<T> first, final Iterable<T>... iterables) {
List<Iterator<T>> allIterables = new LinkedList<Iterator<T>>();
allIterables.add(first.iterator());
for (Iterable<T> iterable : iterables) {
allIterables.add(iterable.iterator());
}
final Iterator<Iterator<T>> iterators = allIterables.iterator();
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Iterator<T> current = iterators.next();
@Override
public boolean hasNext() {
if (current.hasNext()) {
return true;
} else {
if (iterators.hasNext()) {
current = iterators.next();
return current.hasNext();
} else {
return false;
}
}
}
@Override
public T next() {
return current.next();
}
@Override
public void remove() {
}
};
}
};
}
在你关心的情况下,实现是我Dollar library的一部分(作为LGPL3重新发布)。
答案 5 :(得分:1)
为什么不能将它们全部添加为构造函数调用的一部分?
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
for(Looper looper : allLoopers) {
...
}
答案 6 :(得分:1)
根据输入的不同,您可以使用:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks);
allLoopers.add(this);
或:
List<Looper> allLoopers = new ArrayList<Looper>(looperTracks.length + 1);
allLoopers.addAll(looperTracks);
allLoopers.add(this);
答案 7 :(得分:1)
如果由于其动态特性而不想使用Groovy或JRuby,则应考虑使用Scala。 Scala是静态类型的,但比Java更简洁。
答案 8 :(得分:1)
是否要求将所有内容组合到一个列表中?如果没有,这有什么问题?
for (Looper looper : looperTracks) {
doSomething(looper);
}
doSomething(this);
答案 9 :(得分:1)
尝试
Looper[] loop = new Looper[looperTracks.length + 1];
System.arraycopy(looperTracks, 0, loop, 0, looperTracks.length);
loop[looperTracks.length] = this;
for (Looper l : loop) { ... }
但老实说,为什么不循环遍历现有的数组,然后做任何你想做的事情,然后再用this
进行循环?
List
- 版本的上述内容如下:
List<Looper> loop = new ArrayList<Looper>(Arrays.asList(looperTracks));
loop.add(this);
for (Looper l : loop) { ... }
答案 10 :(得分:0)
您可以尝试使用nCopies()
方法使用immutable list。引用API参考,
public static <T> List<T> nCopies(int n, T o)
返回包含的不可变列表 n个指定对象的副本。 新分配的数据对象是 很小(它包含一个参考 到数据对象)。这个方法是 与...结合使用 List.addAll方法来增长列表。该 返回的列表是可序列化的。
这将避免第一次foreach迭代。
答案 11 :(得分:0)
我只是想把它扔出去,但不要试图让你的代码更短,而不是让它变得可读。
当我开始编写代码时,可读代码总是我的目标,仅仅因为我知道在未来的某个时刻要么我自己或其他人要去看它并且必须理解它。