我最初是一个.NET人,最近在Java工作,发现我真的缺少对象的LINQ,特别是对集合进行过滤。
Stack Overflow上的一些人回答了“LINQ for Java?”用一个词来提问:
然而,在网站上它清楚地说明了“Pre-Beta”,而且他们的代码一年多没有提交,所以我猜这个项目已经死了。
是否有人真正使用此功能,和/或有任何使用经验?
第二个最常见的答案似乎是“使用Google Collections”。这是最合适的Java方式吗?
干杯
玛蒂
答案 0 :(得分:5)
您可以使用lambdaj库以更易读的方式选择集合中的项目(以及更多)
答案 1 :(得分:3)
Quaere在Java中处于LINQ的先锋地位,但它不是类型安全的,这是LINQ的主要观点之一。
Querydsl是类型安全的,支持过滤,排序和投影集合。
它还支持JPA / Hibernate,JDO和SQL后端的操作。
语法类似于SQL,区别在于基本顺序是from-where-list。
我是Querydsl的维护者,所以这个答案是有偏见的。
答案 2 :(得分:1)
对于简单的Linq To Objects,我认为可以用Java完成的最好的事情就是这样:
Vector<Integer> numbers = new Vector<Integer>();
numbers.add(42);
numbers.add(3);
numbers.add(16);
numbers.add(92);
numbers.add(9);
Iterable<Integer> filtered = new Where<Integer>(numbers) {
protected boolean predicate(Integer i) { return i > 10; }
};
Iterable<String> converted = new Select<Integer, String>(filtered) {
protected String select(Integer i) { return i.toString(); }
};
for (final String str : converted)
System.out.println(str);
请注意,我没有在一个表达式中将Where
和Select
链接在一起。我可以将filtered
的定义插入到它使用的一个地方,但这可能会使它(甚至)不那么可读。问题是缺乏扩展方法和lambdas。我们最接近lambdas的是这些匿名类声明。它们可以引用封闭范围中命名的对象,但只能引用final
s,因此它们不能改变任何东西(与C#中的lambdas不同)。
同样,冗长冗长的语法也很痛苦。人们经常提出Java应该为只有一个抽象(或接口)方法的情况提供更简单的语法,因此不需要为要覆盖的内容提供名称或类型声明。然后有一个事实是没有类型推断,也没有明显的方法在泛型类构造函数上提供它,因为new Select(filtered)
已经意味着其他东西。
Select
和Where
的实施是:
abstract class Select<TSource, TResult> implements Iterable<TResult>
{
private Iterable<TSource> _source;
public Select(Iterable<TSource> source)
{ _source = source; }
private class Iter implements Iterator<TResult>
{
private Iterator<TSource> _i;
public Iter() { _i = _source.iterator(); }
public void remove()
{ _i.remove(); }
public boolean hasNext()
{ return _i.hasNext(); }
public TResult next()
{ return select(_i.next()); }
}
protected abstract TResult select(TSource source);
public Iterator<TResult> iterator()
{ return new Iter(); }
}
abstract class Where<TSource> implements Iterable<TSource>
{
private Iterable<TSource> _source;
public Where(Iterable<TSource> source)
{ _source = source; }
private class Iter implements Iterator<TSource>
{
private Iterator<TSource> _i;
private TSource _cachedNext;
private boolean _hasCachedNext;
public Iter()
{
_i = _source.iterator();
fetch();
}
public void remove()
{ _i.remove(); }
public boolean hasNext()
{ return _hasCachedNext; }
public TSource next()
{
TSource result = _cachedNext;
fetch();
return result;
}
private void fetch()
{
_hasCachedNext = false;
while (_i.hasNext())
{
_cachedNext = _i.next();
if (predicate(_cachedNext))
{
_hasCachedNext = true;
return;
}
}
}
}
protected abstract boolean predicate(TSource source);
public Iterator<TSource> iterator()
{ return new Iter(); }
}
答案 3 :(得分:1)
SBQL4J可满足您的要求。它是Java语言的类型安全扩展,但它也与Java 6 VM 100%兼容。 SBQL4J提供类似于LINQ到对象的功能。
Daniel的查询示例应该是这样的:
Vector<Integer> numbers = new Vector<Integer>();
numbers.add(42);
numbers.add(3);
numbers.add(16);
numbers.add(92);
numbers.add(9);
Iterable<Integer> filtered = #{ numbers as n where n > 10 };
Iterable<String> converted = #{ numbers.toString() };
for (final String str : converted)
System.out.println(str);
查询语言大约有35个运算符,包括选择,投影,排序,算术运算符,聚合,传递闭包,范围等。
答案 4 :(得分:0)
extra166y addendum to JSR166y有ParallelArray构造。基本上是对象数组的PLINQ。