【问题标题】:@Override TreeSet add methode for add juste 4 elements (on Java)@Override TreeSet add 方法用于添加juste 4 元素(在Java 上)
【发布时间】:2021-12-05 11:54:57
【问题描述】:

我有一个列表,我将它流式传输到带有键和值的 Treemap,其中值是 TreeSet 对于这个 TreeSet,我只是将 4 个第一个元素添加到 Treeset 流中,而不是所有元素

Map<Integer, Set<Person>> stream_exo = ListOfPerson.stream()
                .collect(
                        Collectors.groupingBy(
                                p -> p.getYear(), 
                                TreeMap::new, Collectors.toCollection(TreeSet2::New)));

这里是java的treeSet类:

public class TreeSet<E> extends AbstractSet<E>
                   implements NavigableSet<E>, Cloneable, java.io.Serializable {

    private static final Object PRESENT = new Object();
    
    private transient TreeMap<E,Object> internalMap;
    
    public boolean add(E e) {
        return this.internalMap.put(e, PRESENT)==null;
    }
}

我想为 TreeSet 设置函数(添加),只向 TreeSet 添加 4 个元素,有人可以问我如何做到这一点?

【问题讨论】:

    标签: java set java-stream treeset


    【解决方案1】:

    这与流无关...只是简单的继承。

    创建一个“扩展 TreeSet”的新类“MaxFourTreeSet”并覆盖 add() 函数以添加您的条件。然后,在您的流中使用 MaxFourTreeSet::new 而不是 TreeSet::new。就是这样。

    public class MaxFourTreeSet<E> extends TreeSet<E> {
    
    @Override
    public boolean add(E e) {
        if (this.size() <= 4) {
            return super.add(e);
        } 
        return false;
     } 
    }
    

    (代码不准确)

    【讨论】:

    • 当我这样做时有这个异常:Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.TreeMap.put(Object, Object)" because "this.internalMap" is null
    • 不,你不需要向类添加任何东西,除了 add 函数。我会用一些代码编辑答案。
    • 现在我有另一个例外:Exception in thread "main" java.lang.ClassCastException: class Package.Person cannot be cast to class java.lang.Comparable (Package.Person is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
    • 这与TreeSet本身无关,在你的Person类中实现Comparable并实现方法compareTo(Person p)
    • 我这样做了,但我只有 1 个人而不是 4 个人
    【解决方案2】:

    首先

    要使用TreeSet“有序集”),值(&lt;V&gt;)必须实现Comparable&lt;V&gt;或者我们必须提供@987654325 @@TreeSet 建设。

    第二

    检查一下(如果我们没看错的话):

    package com.example;
    
    import static java.util.stream.Collectors.collectingAndThen;
    import static java.util.stream.Collectors.groupingBy;
    import static java.util.stream.Collectors.toSet;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    public class Test {
        public static void main(String[] args) {
            // test data:
            List<Person> list = List.of(new Person(1969), new Person(1969), new Person(1969), new Person(1969),
                new Person(1969), // 5
                new Person(1971), new Person(1971), new Person(1971), new Person(1971),
                new Person(1971), // 5
                new Person(1999), new Person(1999) // 2
            );
            // action:
            Map<Integer, Set<Person>> stream_exo = list.stream()
                .collect( //..as we had
                    groupingBy( // ...
                        p -> p.year, // ... key - function
                        collectingAndThen( // value - "downstream"
                            toSet(), // collector - function (downstream)
                            s ->  s // (and then) set - (finalizer) fuction
                                .stream() //  stream once more ;(, unfortunately i found no nicer way
                                .limit(4) // limit to 4, and finally:
                                .collect(  // ...collect
                                    toSet()  // to set TreeSet::new, when Person is Comparable<Person>
                                )
                        ) // end-collectingAndThen
                    ) // end-groupingBy
                ); // end-collect
            // output verification:
            stream_exo.forEach((k, v) -> {
                System.out.format("%s:\t%d%n", "key", k);
                v.forEach(p -> System.out.println(p));
            });
    
        }
    }
    
    class Person {
        final int year;
    
        Person(int pYear) {
            year = pYear;
        }
    }
    

    输出:

    key:    1969
    com.example.Person@31befd9f
    com.example.Person@1c20c684
    com.example.Person@2f2c9b19
    com.example.Person@13221655
    key:    1971
    com.example.Person@3e3abc88
    com.example.Person@1218025c
    com.example.Person@548c4f57
    com.example.Person@816f27d
    key:    1999
    com.example.Person@53d8d10a
    com.example.Person@6ce253f1
    

    所以collectingAndThen(再发给stream(),再发给limit(),再发给collect())就是我对这个特殊要求的回答!


    第三

    如果我们想使用TreeSet,我们必须实现上面提到的(First)接口,“...and finally”:

    collect(toSet(TreeSet::new)))));
    

    终于

    让它真正成为TreeMap

    TreeMap<Integer, Set<Person>> stream_exo = list.stream()
       ....
    

    我们需要:

    ...
    groupingBy(
        p -> p.year, 
        TreeMap::new, // do additonally this!
        collectingAndThen( ...
    

    还要嵌套TreeSets(不修改Person,基于person.year),就是这样:

    TreeMap<Integer, Set<Person>> stream_exo = list // TreeMap result (Integer IS Comparable<Integer>;)
        .stream()
        .collect(
            groupingBy(
                p -> p.year,
                TreeMap::new,
                collectingAndThen(
                    toSet(), // if we want the "intermediary" set also as TreeSet(ordered!), then here!
                    s -> 
                        s.stream()
                        .limit(4)
                        .collect(
                            toCollection(() -> {  // TreeSet leafs:
                                return new TreeSet<> ( // with inline comparator
                                    (p1, p2) -> Integer.compare(p1.year, p2.year));
                            }
                        )
                )
            )
        );   
    

    ...但是year 旁边的Comparable&lt;Person&gt; 在这里没用,因为year 已经分组/唯一。;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 2021-06-05
      • 2016-10-24
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多