番石榴供应商:使用每个元素自己的功能转换集合

时间:2011-09-05 15:46:53

标签: java guava

假设我有一个Node类,它有一个Function作为实例变量。

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);
}

果然,变换遍历节点List并将函数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()

但在verison r09中似乎不存在。

4 个答案:

答案 0 :(得分:2)

我对你要做的事情感到困惑...... Supplier在这里似乎没用。每个Node都有自己的Function。您希望通过将每个Node的{​​{1}}应用于自身来转换Node的集合。那么为什么不给Function类一些方法:

Node

然后你只需// may want a better name public Double applyFunction() { return function.apply(this); } 使用transform这样:

Function

答案 1 :(得分: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);
    }
}

答案 2 :(得分:1)

如果我们假设Node通过公共getter公开其函数,则有第三种方法可以在不修改Node类的情况下执行此操作。

使用匿名类:

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);
    }
}

答案 3 :(得分:0)

我的问题的关键是这句话:“所以我认为供应商会有所帮助。”答案是它没有。我试图找到它的用途 - 在Map创建之外,这似乎是它的主要用途。我提到过一种供应商方法,但似乎是MIA。也许这可能是一个RFI for tranform被重载以将Iterable作为第二个参数