当前位置: 首页 > 知识库问答 >
问题:

无限制的Java流参数限制(MongoDB不一致)

梁丘波
2023-03-14
public List<Integer> getItems(Long limit) {
    return IntStream.range(1, 10)
            .limit(limit)
            .boxed()
            .collect(Collectors.toList());
}  

我的尝试:

    Long limit5 = 5L;
    System.out.println("With limit 5:" + getItems(limit5));
    // works fine: 5 items

    Long noLimitZero = 0L;
    System.out.println("Without limit (zero): " + getItems(noLimitZero));
    // why 0 mean "no items" instead of "all items"

   Long noLimitNegative = -1L;
    System.out.println("Without limit (negative number): " + getItems(noLimitNegative));
    // IllegalArgumentException

    Long noLimitNull = null;
    System.out.println("Without limit (null): " + getItems(noLimitNull));
    // NullPointerException

传递long.max_value不是解决方案。

例如,MongoDB的finditerable#limit可以将0null作为无限制。

public List<Integer> getItems(Long limit) {
    MongoDatabase mongo = new MongoClient().getDatabase("example");
    MongoCollection<Document> documents = mongo.getCollection("items");
    FindIterable<Document> founded = documents.find();
    List<Integer> items = new ArrayList<>();
    for (Document doc : founded.limit(limit.intValue())) {
        items.add(doc.getInteger("number"));
    }
    return items;
}

方法之间的这种不一致会导致不兼容,例如,一个接口带有方法list getItems(Long limit) 和两个实现:in memory和MongoDB。

方法流#skipfinditerable#skip中的一致性得到了保留。

          --------------------------
          | Java       | Mongo     |
------------------------------------
limit = 0 | none items | all items |
------------------------------------
skip = 0  | none skip  | none skip |
------------------------------------
public static List<Integer> getItems(Long limit) {
    if (limit == null || limit == 0 || limit == -1) {
        return IntStream.range(1, 10)
                .boxed()
                .collect(Collectors.toList());
    } else {
        return IntStream.range(1, 10)
                .limit(limit)
                .boxed()
                .collect(Collectors.toList());
    }
}

或:

public static List<Integer> getItems(Long limit) {
    IntStream items = IntStream.range(1, 10);
    if (limit != null && limit != 0 && limit != -1) {
        items = items.limit(limit);
    }
    return items.boxed()
            .collect(Collectors.toList());
}

有更好的方法实现方法之间的一致性limit

共有1个答案

武元白
2023-03-14

所以你要做的事情有几层问题。

您说“实用性不是一个参数”,这很好,但让我指出long.max_value确实超过了地球上的原子数量,因此从数据库中获得更多条目的可能性非常小。更不用说您继续将这些数据收集到列表中,因此您可能也会在自己的应用程序中遇到内存问题。

所以第二件事是limit()的语义是,它对条目的数量施加了一个固定的限制,而“无穷大”不是一个固定的限制;因此limit()并不是您所需要的。

第三,你似乎在寻找一种方法,这样我们就有了一个你可以使用的模式,那就是维护你自己的计数器。您想要的是像atomicbiginteger这样的东西,它在JDK中不存在,但在这里显示。

所以您要做的是创建一个谓词,如下所示

class BelowValue<T> implements Predicate<T> {
    BigInteger limit = BigInteger.ZERO;
    AtomicBigInteger counter = new AtomicBigInteger();

    public BelowValue(BigInteger limit) {
        this.limit = limit;
    }        
    public BelowValue() {}

    public boolean test(T ignored) {
        // short circuit on zero
        if (BigInteger.ZERO.compareTo(limit) == 0) { return true; }

        // check actual condition
        return  counter.incrementAndGet().compareTo(limit) > 0;
    }
}

然后您可以在您的流(Java8)中使用它

Predicate<T> filter = new BelowValue<>(limit);
return stream
    .filter(filter)
    .boxed()
    .collect(Collectors.toList());
 类似资料:
  • 主要内容:limit() 方法,skip() 方法当我们在使用 find() 方法查询集合中文档的时侯,会一次性的将所有符合条件的文档全部展示出来,但我们可能并不需要全部的查询结果(比如在做分页处理时),这时该怎么做呢?下面就来介绍一下。 limit() 方法 MongoDB 中要限制查询的记录条数可以使用 limit() 方法,该方法接收一个数字作为参数,用来设置要显示的记录数,如下所示: db.collection_name.find().l

  • 问题内容: 是否存在Java 8流操作来限制(可能是无限的)直到第一个元素与谓词不匹配? 在Java 9中,我们可以使用下面的示例来打印所有小于10的数字。 由于Java 8中没有这样的操作,以一般方式实现它的最佳方法是什么? 问题答案: 操作并已添加到JDK9。你的示例代码 在JDK 9下编译和运行时,其行为将完全符合你的预期。 JDK 9已发布。可在此处下载:http : //jdk.java

  • 在GET操作中,我们对查询参数的长度是否还有任何限制。前面我想我用的是255,这似乎增加了,但我不知道增加的限制是什么。 我面临的问题是,我尝试GETendpoint,如http://localhost:8080/data/ids=<5000 comma seaprated ids>,但失败了 但是具有500个ID(如http://localhost:8080/data/ids=<500 comm

  • 问题内容: 顾名思义,数据输出流方法writeByte(int)在流上写入一个1字节int。 这有什么限制?是256还是带符号的-128到127? 问题答案: 调用。的文档说: 将指定的字节(参数b的低8位)写入基础输出流。 因此,参数所位于的整数范围无关紧要。两个相差倍数的参数将导致写入相同的字节。 一种简单的测试方法是使用。试试这个程序: 输出是因为相同的内容已被写入两次。

  • 通过执行一个简单的循环创建线程java程序,当我使用-Xmx2048M时,AIX的线程数限制在900左右,当我将该参数降低到-Xmx1024M时,线程数限制增加到2000左右。我的ulimited属性都是无限的:ulimited-a时间(秒)无限文件(块)无限数据(kbytes)无限堆栈(kbytes)无限内存(kbytes)无限核心转储(块)无限nofile(描述符)无限线程(每个进程)无限进程

  • 问题内容: 无界通配符(例如)与界为(例如)的有界通配符之间是否有区别? 我记得在某处读到,泛型的早期草案有所不同,但现在找不到该来源了。 问题答案: 作为方法,如果class / interface / constructor / method声明了bound(不是),则有所不同。