传入两个lambda函数

时间:2018-04-19 18:42:23

标签: java lambda

我想将两个lambda表达式(或者类似的东西,我仍然熟悉所有术语)传递给一个方法;第一个将获得一个项目列表,第二个将从(每个)项目中检索一个Integer对象。

所以我想要一个像这样的方法:

private List<Integer> getRecentList(List<Integer> searchParams, 
                                    Function<List<Integer>, List<Integer>> listGetter,
                                    Supplier<Integer> idGetter)
{
  List<Object> objectList = listGetter.apply(searchParams);
  List<Integer> idList = new ArrayList<>();
  for (Object o: objectList)
  {
    idList.add(idGetter.get());
  }
  return idList;
}

并称之为:

List<Integer> idList = setRecentList(searchParams, 
                                     (a) -> serviceOne.getItemList(a), 
                                     Item::getItemId);

所以第一个函数是一个调用一个实例变量的函数,被调用的方法可以访问它,第二个函数是第一个函数作为列表返回的任何一个对象的实例方法。

但是(eclipse)编译器不喜欢Item::getItemId,最后有或没有括号。

我的语法错误,或者这个想法有什么问题吗?

经过许多有用的评论后编辑 - 感谢大家!

我还有一个问题。我现在有一个方法,我认为做了我想要的,但我不知道如何传递第二个表达式来调用它。这是方法:

private List<Integer> getRecentList(List<Integer> salesCodeIdList,
                                    Function<List<Integer>, List> listGetter, 
                                    Function<Object, Integer> idGetter                                 
                                    ) {
    List<Object> objectList = listGetter.apply(salesCodeIdList);
    List<Integer> idList = new ArrayList<>();
    for (Object o : objectList) {
        idList.add(idGetter.apply((o)));
    }
    return idList;
}

AFAIK,我必须在getter规范中保留第二个List raw,因为不同的getter将在其列表中返回不同类型的对象。

但我仍然不知道如何调用它 - 我想传递一个从特定对象实例获取id的方法,即我想在其中一个的ID上传递一个getter listGetter返回的对象。这将是不同调用的不同类型的对象。我该如何调用它?

回到示例,如果我有一个带有getSupplierId()的Supplier类和一个带有getVendorId()的Vendor类,并且我无法更改这些类,我可以传入正确的方法来调用列表取决于哪个getter检索列表?

2 个答案:

答案 0 :(得分:3)

您获得错误的一个可能原因隐藏在您的方法实现中:

private List<Integer> getRecentList(List<Integer> searchParams, 
                                Function<List<Integer>, List<Object>> listGetter,
                                Supplier<Integer> idGetter)
{
    List<Object> objectList = listGetter.apply(searchParams);
    List<Integer> idList = new ArrayList<>();
    for (Object o: objectList)
    {
        idList.add(idGetter.get()); // <<<<<==== Here
    }
    return idList;
}

请注意,来自o循环的for未在呼叫中使用,表明idGetter会凭空透露身份证明。当然不是这样:你需要将一个项目传递给idGetter,这意味着该调用应该是

idList.add(idGetter.apply(o));
  

(来自评论)我无法在方法中投射,我不知道要投射到哪种类型的物体。

反过来意味着idGetter应为Function<Object,Integer>

for (Object o: objectList)
{
    idList.add(idGetter.apply(o));
}

由于您希望为不同类型的列表重用相同的函数,因此调用必须使用在调用者处执行强制转换的lambda,即在您知道类型的位置:

List<Integer> idList = setRecentList(searchParams, 
                                 (a) -> serviceOne.getItemList(a), 
                                 (o) -> ((Item)o).getItemId());

答案 1 :(得分:1)

L = range(1000)不是Item::getItemIdSupplier<Integer>是一个lambda函数,它不带参数并返回Supplier<Integer>。但Integer需要Item::getItemId才能获取ID。

这可能是你想要的。注意我已经更改了您的方法签名,以匹配您从项目中获取ID的想法。

Item

编辑:如果您希望它处理多种class Item { int id; Item (int i) { id = i; } int getItemId() { return id; } } private static List<Integer> getRecentList(List<Integer> searchParams, Function<List<Integer>, List<Item>> listGetter, Function<Item, Integer> idGetter) { List<Item> itemList = listGetter.apply(searchParams); List<Integer> idList = new ArrayList<>(); for (Item item: itemList) { idList.add(idGetter.apply(item)); } return idList; } ,并且它们都有ID,您可以执行以下操作。首先,定义一个界面来表示您的不同类型的Item都具有ID:

Items

然后,您的方法应该使用interface ItemWithId { abstract int getItemId(); } class ItemA implements ItemWithId { int id; ItemA(int i) { id = i; } public int getItemId() { return id; } } class ItemB implements ItemWithId { int id; ItemB(int i) { id = i; } public int getItemId() { return id; } } 而不是ItemWithId

Item

最后,您可以通过将private List<Integer> getRecentList(List<Integer> searchParams, Function<List<Integer>, List<ItemWithId>> listGetter, Function<ItemWithId, Integer> idGetter) { List<ItemWithId> itemList = listGetter.apply(searchParams); List<Integer> idList = new ArrayList<>(); for (ItemWithId item: itemList) { idList.add(idGetter.apply(item)); } return idList; } ItemA转换为ItemB来调用此方法:

ItemWithId

另一个编辑:好的,因此您无法更改List<Integer> idList = getRecentList(searchParams, (a) -> getItemList(a), (item) -> ((ItemWithId) item).getItemId()); ItemA。你仍然可以使它工作:

ItemB