我有这样的事情:Java集合过滤
public class Foo {
public String id;
}
和
Vector<Foo> foos;
我需要通过ID来获得从集合对象。
在C#中,我会做这样的:foos.Where(o => o.id = 7)
怎样做,在Java中的最佳方式是什么?
我有这样的事情:Java集合过滤
public class Foo {
public String id;
}
和
Vector<Foo> foos;
我需要通过ID来获得从集合对象。
在C#中,我会做这样的:foos.Where(o => o.id = 7)
怎样做,在Java中的最佳方式是什么?
您可能希望将您的数据存储在地图<整数,Foo>而不是列表< Foo>中。例如,一个TreeMap将按顺序排列所有内容。
一开始之前进行排序,我建议使用ArrayList<Foo>
,而不是Vector<Foo>
- ArrayList
几乎总是最好Vector
。
使用Google Collections API,特别是Iterables.filter。现在它非常笨重 - 由于缺少lambda表达式,您需要预先设置谓词,或者使用匿名内部类。另外,Java没有扩展方法,所以你可以调用Iterables.filter(collection, predicate)
而不是collection.filter(predicate)
。这两项将在Java 7中
注有所简化,使用filter
会发现一个Iterable<Foo>
- 如果你只需要在第一场比赛中,使用Iterables.find
相反,这是Enumerable.First<T>(Func<T, bool>)
在LINQ的等价物。
过滤函数的问题在于迭代器遍历集合的所有元素,而不管您正在搜索的对象在哪里。只要找到对象,就想立即退出循环。 – 2017-09-11 11:10:53
@LucaFagioli:与更现代的Java流相比,Iterables现在有点不受欢迎,但我的理解是'Iterables.filter'仍然是懒惰的 - 您可以只返回返回的iterable的第一个元素,那就没问题了。 – 2017-09-11 11:15:39
是的,你可以,但我的意思是说,要返回迭代器,该功能仍然需要检查集合中的所有元素。从[文档](https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/Iterables.html#filter-java.lang.Iterable-java.lang。 Class-):_返回包含所有类型为'desiredType'的元素的未过滤的视图。这导致_average_个案的复杂度为O(n),而手动搜索对象时_worst_个案复杂度为O (N)。 – 2017-09-11 11:36:59
首先,不使用Vector
,使用ArrayList
ArrayList<Widget> widgets = ...
Widget found = null;
for (Widget o : widgets)
{
if (o.id == 7)
{
found = o;
break;
}
}
如果你有一个ArrayList(或类似的 - 即从Collection的图书馆的东西),然后Apache Commons Collections有很多的设施,为过滤/迭代等
注意,与乔恩的回答中引用的谷歌集合库中,有一个为泛型的支持。
我认为,在Java中,传统的方式是通过列表进行迭代,并与你看了(复杂度为O(n))的ID搜索富。如果这样慢,你可能会考虑使用HashMap结构,将foo映射到它的索引。
人们可以“隐藏”查找通过继承集合类:
public class ListOfFoos extends ArrayList<Foo> {
public Foo getFooByIndex(String index) {
// do your lookup here
}
}
,并使用ListOfFoos而不是ArrayList的从现在起一个新的集合类型,允许直接存取权限由它的索引号富。
以下类型提供了对序列的过滤。这个解决方案是通用的,但不适用于集合或排序的序列,每个序列都提供更有效的方法来查找和删除与某些示例匹配的元素。
首先,定义一个Iterator
型这真是懒发电机适配器:
abstract class IteratorHusk<T> implements Iterator<T>
{
@SuppressWarnings("unchecked")
protected IteratorHusk()
{
value_ = nil();
}
@SuppressWarnings("unchecked")
protected T nil()
{
return (T) NIL;
}
protected abstract T yield();
private boolean tryPop()
{
value_ = yield();
return NIL != value_;
}
@SuppressWarnings("unchecked")
private T take()
{
final T current = value_;
value_ = (T) NIL;
return current;
}
public final boolean hasNext()
{
return NIL != value_ || tryPop();
}
public final T next()
{
if (NIL == value_ && !tryPop())
{
throw new NoSuchElementException();
}
return take();
}
public void remove()
{
throw new UnsupportedOperationException();
}
// We want to tolerate null as a possibly valid value.
private static final Object NIL = new Object();
private T value_;
}
这是2009年和Java仍然缺乏倒闭和一流的功能,所以我们不好意思地介绍这个家庭:
interface UnaryFunction<T, U>
{
T eval(U argument);
}
现在,围绕一元谓词包裹一个生成器来构建一个序列过滤器:
class FilteringIterator<T> extends IteratorHusk<T>
{
public FilteringIterator(Iterator<? extends T> iter,
UnaryFunction<Boolean, ? super T> pred)
{
iter_ = iter;
pred_ = pred;
}
@Override
protected T yield()
{
while (iter_.hasNext())
{
final T val = iter_.next();
if (!pred_.eval(val))
{
return val;
}
}
return nil();
}
private final Iterator<? extends T> iter_;
private final UnaryFunction<Boolean, ? super T> pred_;
}
现在,暴露出一个方便的功能:
public static <T>
Iterator<T> lazyFilter(UnaryFunction<Boolean, ? super T> pred,
Iterator<? extends T> source)
{
return new FilteringIterator<T>(source, pred);
}
自己编写所有的代码将是愚蠢的,然后不得不单独测试它(这比写它更难,相信我)..只是使用一个库。 – 2009-11-24 15:13:47
这是我为内部使用而编写的较大型图书馆的一部分。有几个生成器与IteratorHusk类型一起使用。过滤一个包装的迭代器就是其中之一。 – seh 2009-11-24 15:41:06
随着Google Collections,这将是:
Lists.newArrayList(Iterables.filter(foos, new Predicate<Foo>() {
public boolean apply(Foo input) {
return input != null && "7".equals(input.id);
}
}));
Iterables.filter(和Collections2.filter,这不相同),得到你可以看到过滤后的集合,就像seh的概念一样,但代码少。为了再次创建列表,我将它传递给newArrayList Google Collection的列表实用工具类的方法。
就像其他人一样,我强烈建议不要使用Vector作为声明。相反,尽量使用可能的最通用的类型,例如,列表< Foo>或甚至收集< Foo>。另外,除非您需要Vector的同步功能,否则请使用ArrayList(或其他适合该问题的其他类型)。
看一看lambdaj。它允许以伪功能和非常可读的方式对集合进行操作,过滤,排序和聚合。
sweetener项目的限制类解决了这个问题。
例子:
Collection<Foo> filteredList = Collections.filter(foos, Criteria.newCriteria().add(Restrictions.equals("id", 7)));
如果您收藏已经排序,你可以把二进制搜索,让你的O最坏情况的复杂性优势(log n)的:
如果您可以自由选择数据结构,请使用HashMap<String, Object>
,这会给您带来O(1)的复杂性。
ps:使用ArrayList
而不是Vector
。
你正在寻找适应序列或任何集合类型?如果只有序列,你能否假定序列被排序?适合每种算法和时间复杂性成本的算法是不同的。将一个解决方案应用于所有类型的集合将会对其中至少一个集合造成损害。 – seh 2009-11-24 12:39:31
是的,ids排序他们来了像1,2,3,虽然他们是字符串 – Omu 2009-11-24 12:47:04