2009-07-08 72 views
5

我最初是一名.NET人,最近在Java工作,发现我确实缺少LINQ to Objects,专门针对集合执行过滤。Quaere - 任何人使用它? (LINQ to Objects)

Stack Overflow上的一些人已经回答了“LINQ for Java?”一个字的问题:

Quaere

然而,在网站上也明确指出“预测试版”,而且也一直没有提交给他们的代码一年多了,所以我猜测该项目已经死了。

是否有人真的使用过它,和/或有任何经验?

第二个最常见的答案似乎是“使用Google Collections”。这是最合适的Java方式吗?

干杯

马蒂

+1

对于linq到对象检查github.com/nicholas22/jpropel-light,真实的例子:new String [] {“james”,“john”,“john”,“eddie”} .where(startsWith(“j”)) .toList()不同(); – 2011-10-08 10:21:50

回答

5

您可以通过使用lambdaj库

http://code.google.com/p/lambdaj/选择更可读的方式集合中的项目(以及更多)

+0

+1看起来非常好,谢谢你的链接。 – skaffman 2009-09-12 08:03:09

1

对于简单的LINQ到对象,我认为最好的可以用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); 

请注意,我还没有得到WhereSelect链接在一起表达。我可以将filtered的定义插入到其使用的位置,但这可能会使其(甚至)更不可读。问题是缺乏扩展方法和lambda。我们可以最接近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

Quaere与LINQ在Java中的先锋地位,但不类型安全,这是LINQ的一个要点。

Querydsl是类型安全,并支持过滤,排序和突出类别。

它支持对JPA/Hibernate,JDO和SQL后端的操作。

语法与SQL类似,不同之处在于基本顺序来自where-list。

我是Querydsl的维护者,所以这个答案是有偏见的。

1

SBQL4J可能会满足您的要求。它是Java语言的类型安全扩展,但它也与Java 6 VM完全兼容。 SBQL4J提供了与LINQ到对象类似的功能。

丹尼尔的查询例子应该是这样的:

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运营商的查询语言,包括选择,投影,排序,算术运算符,聚集,传递闭包,范围等