2011-09-05 34 views
4

假设我有一个具有Function作为实例变量的Node类。番石榴供应商:使用各个元素自己的功能转换一个集合

public class Node { 
    private Function<Node, Double> function; 
    ... 

我有这些节点的列表:

List<Node> nodes = Lists.newLinkedList(); 
nodes.add(new Node(someFunction)); 
nodes.add(new Node(someOtherFunction)); 

我可以这样做:

public Collection<Double> getValues() { 
    SomeFunction f = new SomeFunction(); 
    return Collections2.transform(nodes, f); 
} 

果然,在节点列表变换迭代,并应用函数f于每个像mapcar的元素。

我想要做的是让变换使用每个节点元素所具有的功能。

所以我虽然供应商会帮助。

class NodeSupplier implements Supplier<Node> { 
    Iterator<Node> iterator; 

    NodeSupplier(Iterable p) { 
     iterator = Iterators.cycle(p); 
    } 

    @Override 
    public Node get() { 
     return iterator.next(); 
    } 
} 

然后获得一个节点的函数。

class SupplierGetter implements Function<Supplier<Node>, Node> { 
    @Override 
    public Node apply(Supplier<Node> from) { 
     return from.get(); 
    } 
} 

然后撰写他们:

FunctionGetter fg = new FunctionGetter(); 
NodeSupplier sup = new NodeSupplier(this); // the this class is Iterable 
Supplier<Function<Node, Double>> supplier = Suppliers.compose(fg, sup); 

但后来它给了我一个类型不匹配时,我尝试使用它:

Collections2.transform(nodes, supplier); 

它都想suppler.get(),这是所谓的一旦。

Collections2.transform(nodes, supplier.get()); 

有没有更简单的方法?

我看到的

Suppliers.supplierFunction() 

提及,但似乎s到不verison R09存在。

回答

2

我很困惑你正在尝试做什么...... Supplier在这里似乎没有用。每个Node都有自己的Function。您希望通过将Node的每个Function应用于其自身来变换Node的集合。那么,为什么不干脆放弃了Node类的一些方法:

// may want a better name 
public Double applyFunction() { 
    return function.apply(this); 
} 

然后你只transform使用Function这样的:

public Double apply(Node node) { 
    return node.applyFunction(); 
} 
+0

+1打我给它 –

+0

这就是我在做什么。 (我称它为getValue()而不是applyFunction())。不幸的是,与其他课程相比,这打破了2个建模平台。所以我在其他地方寻求帮助。供应商在这里没有帮助。 –

2

除了事实,我也有关于你我的疑惑正在尝试做的,下面要达到你所要求的:

class Node { 
    private Function<Node, Double> function; 

    private static Function<Node,Double> applyFunction = new Function<Node,Double>() { 
     @Override 
     public Double apply(final Node input) { 
      return input.function.apply(input); 
     } 
    }; 

    public static Iterable<Double> transform(final Iterable<Node> nodes) { 
     return Iterables.transform(nodes, applyFunction); 
    } 
} 
+0

如果我正确地理解了你,因为你通过拖拽供应商来认真地理解我。 – jvdneste

+0

这与ColinD的回复基本相同,只是更加明确。 – jvdneste

+0

谢谢你的怀疑。这有帮助。我只是不知道如何在不拖动供应商的情况下询问供应商的问题。 –

1

还有就是要做到这一点,而无需修改日第三条路e节点类,如果我们假设Node通过公共getter公开它的功能。

使用匿名类:

public Collection<Double> getValues() { 
    return Collections2.transform(nodes, new Function<Node, Double>() { 
     @Override public Double apply(Node node) { 
      return node.getFunction().apply(node); 
     } 
    }); 
} 

使用枚举单件模式(我更喜欢,因为它更清晰)

public Collection<Double> getValues() { 
    return Collections2.transform(nodes, ApplyNodeFunction.INSTANCE); 
} 

/** 
* A {@link Function} that applies the {@link Node}'s own function on itself. 
*/ 
private enum ApplyNodeFunction implements Function<Node, Double> { 
    INSTANCE; 

    @Override public Double apply(Node node) { 
     return node.getFunction().apply(node); 
    } 
} 
0

我的问题的关键是这句话:“所以我认为供应商会提供帮助。”答案是它没有。我试图找到它的用途 - 在地图创作之外,这似乎是它的主要用途。有一个我提到的供应商方法,但它似乎是MIA。也许,这可能是一个变换分析RFI超载采取以Iterable作为第二个参数

+0

供应商有一些用途(例如,与Suppliers.memoize()结合使用时会懒惰地构造一个单例),但在您的情况下,它会使事情不必要地复杂化。你有一个类型不匹配,因为你试图将一个供应商传递给transform()方法,该方法的参数应该是一个Function。 Suppliers.compose()不做你想做的事情:它返回一个新的供应商,而不是一个函数。你想要的是Suppliers.supplierFunction(),它似乎存在于r09中:http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/base/Suppliers.html(最后一个函数) –

+2

此外,由此产生的函数将是有状态的,这是危险的。每次调用“apply()”都会改变函数的状态(通过选择Iterable中的下一个元素)。 –