首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用lamba筛选通用集合

使用lamba筛选通用集合
EN

Stack Overflow用户
提问于 2018-11-06 12:03:34
回答 3查看 318关注 0票数 0

末尾重新定义了问题

--------------------------------------------

我必须编写两个泛型方法,以筛选泛型类型的集合。

第一个removeDuplicates和来自Collection<的可选空?扩展对象>。

第二个removeDuplicates和可选的Collection<字符串中的空/空。

代码语言:javascript
复制
private <T extends Collection<C>, C extends Object> T  removeDuplicatesFromCollection(T collection, boolean skipNull)
{
    if(collection == null)
    {
        return collection;
    }

    final HashSet<C> tmp = new HashSet<C>();

    for(C element : collection)
    {
        if(element == null && skipNull)
        {
            continue;
        }
        else
        {
            tmp.add(element);
        }
    }

    collection.clear();
    collection.addAll(tmp);

    return collection;
}

否则我不知道怎么解决这个问题。因此,我使用HashSet来筛选惟一的、清除原始集合并添加哈希集的所有条目。

首先,我试图通过流处理和使用lambda表达式来解决这个问题,但在这里我也找到了使用collect()来处理的问题。

首先,我尝试了流化和使用lambda表达式,但没有

很管用,但我相信一定有更好的办法。

第一种方法是从Collection中删除重复项和空项。我想再次使用lambda指令和apache StringUtils过滤这个列表,但是我不知道如何处理集合和泛型类型T。

代码语言:javascript
复制
private <T extends Collection<String>> T removeDuplicationsFromStringCollection(T collection, boolean skipNull, boolean skipEmpty)
{
    if(collection == null)
    {
        return collection;
    }

    T removedDuplicates = removeDuplicatesFromCollection(collection, skipNull);

    if(removedDuplicates == null || !skipEmpty)
    {
        return removedDuplicates;
    }
    else
    {
        removedDuplicates.().filter(s -> StringUtils.isNotBlank(s)).collect(T::new); <== [X Cannot instantiate the type T ]
    }
}

有人能帮忙完成这份工作吗?如果有人对第一种方法有更好的解决办法,我也会感激的,因为我自己还没有完全满意它。

非常感谢

??编辑??编辑?

我不知道哪种集合是从方法输入的,把输出类型必须是输入类型的集合。HashSet =>方法=> HashSet =>返回ArrayList =>方法=> ArrayList =>返回

我不喜欢修改输入集合,但这是保持集合类型的唯一方法。问题不是在流过程中过滤列表,而是在流的末尾进行collect( ),并根据inputtype创建泛型类型。问题是为输出集合保留输入集合的类型。

让我重新表述并简化这个问题,也许我不应该围绕着我想要做的事情写那么多。有任何有用的提示和提示,但核心问题没有得到解决

代码语言:javascript
复制
private <T extends Collection> T  doFilter(T pCollection, ....
{
    /** removed code for simplifing **/
    return pCollection.stream()
    /*.filter(....)*/
    .collect(  Collectors.toCollection( ?>>  T  <<?? ) );
}

有人能告诉我如何收集(Collectors.toCollection(T))在一个具有通用类型的λ中吗?

因此,列表=> doFilter() =>列表

ArrayList => doFilter() => ArrayList

设置=> doFilter() =>集

LinkedHashSet => doFilter() => LinkedHashSet

T => doFilter() => T

……

EN

回答 3

Stack Overflow用户

发布于 2018-11-06 12:16:40

使用java 8流API确实会带来更清晰的实现:

代码语言:javascript
复制
public <T extends Collection<Object> T removeDuplicatesFromCollectionAndFilterNull(T collection) {
  return collection.stream()
    .filter(Objects::isNull) // Method Reference to Objects.isNull(object)
    .collect(Collectors.toSet()); // Collect to set to remove duplicates
}

类似的方法也可以用来解决第二个问题。请注意,collection方法不使用lambda来创建集合(而且T::new不会工作,因为Java不知道该方法是否有默认构造函数),而是一个收集器。这个指南可能会有帮助。

票数 1
EN

Stack Overflow用户

发布于 2018-11-06 12:23:51

您可以在流上使用distinct()方法

代码语言:javascript
复制
 Collection<String> list = Arrays.asList("A", "B", "C", "D", "A", "B", "C");
   // Get collection without duplicate i.e. distinct only
    List<String> distinctElements = 
    list.stream().distinct().collect(Collectors.toList());

这将返回所有非null的不一致元素:

代码语言:javascript
复制
public <T extends Collection<Object>> T removeDuplicatesFromCollection(T collection) {
        return  collection.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        }

您还可以在供应商中使用此示例:

代码语言:javascript
复制
  public static <T,U extends Collection<T>> U removeDuplicatesFromCollection(Iterable<T> iterable , Supplier<U> collectionType) {
        return  StreamSupport.stream(iterable.spliterator(),false).filter(Objects::nonNull).distinct().collect(Collectors.toCollection(collectionType));
    }
  List<String> strings = Arrays.asList("A","B",null,"B");
        removeDuplicatesFromCollection(strings, ArrayList::new).forEach(System.out::println);
票数 0
EN

Stack Overflow用户

发布于 2018-11-06 12:40:38

我认为主要的问题是以某种方式知道您正在处理的特定类型的集合,因此您可以创建这个特定类型的新集合,并将过滤后的值添加到其中。更改参数是错误的做法,即不应该修改接收到的集合。

因此,我将使用Supplier<T>作为工厂来创建特定的集合:

代码语言:javascript
复制
private <T extends Collection<C>, C> T removeDuplicatesFromCollection(
        T collection, 
        boolean skipNull,
        Supplier<? extends T> factory) {

    if (collection == null) return null;

    // Remove duplicates, but keep insertion order (that's what LinkedHashSet is for)
    Set<C> noDuplicates = new LinkedHashSet<>(collection);

    // Remove nulls from the set if the flag is on
    if (skipNull) noDuplicates.removeIf(Objects::isNull);

    // Use the factory to create an empty instance of the collection 
    T newCollection = factory.get();

    // Add the no duplicates set, possibly without nulls
    newCollection.addAll(noDuplicates);

    return newCollection;
}

现在,您可以按照以下方式使用上面的方法:

代码语言:javascript
复制
List<Integer> list = Arrays.asList(1, 2, 3, null, 5, 6, 1);

ArrayList<Integer> noDupsNoNulls = removeDuplicatesFromCollection(
        list,
        true,
        ArrayList::new); // [1, 2, 3, 5, 6]

编辑:--如果您已经有了对每个具体集合类型执行相同操作的方法,比如一个用于List<C>,另一个用于Set<C>等等,则不需要将所有调用都更改为这些方法。您所需要做的就是更改它们的实现,以便它们现在指向上面的新方法。

例如,假设您已经有了以下方法:

代码语言:javascript
复制
private <C> HashSet<C> removeDuplicatesFromCollection(
        HashSet<C> collection, 
        boolean skipNull) {

    // .....

}

您可以将其更改如下:

代码语言:javascript
复制
private <C> HashSet<C> removeDuplicatesFromCollection(
        HashSet<C> collection, 
        boolean skipNull) {

    return removeDuplicatesFromCollection(collection, skipNull, HashSet::new);
}

如果您有另一个用于ArrayList的方法

代码语言:javascript
复制
private <C> ArrayList<C> removeDuplicatesFromCollection(
        ArrayList<C> collection, 
        boolean skipNull) {

    // .....

}

您可以将其更改如下:

代码语言:javascript
复制
private <C> ArrayList<C> removeDuplicatesFromCollection(
        ArrayList<C> collection, 
        boolean skipNull) {

    return removeDuplicatesFromCollection(collection, skipNull, ArrayList::new);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53171532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档