Java 用流将列表汇总到一个极限
如何获取记录,哪些计数总和应在限制范围内。在下面的示例中,有Java 用流将列表汇总到一个极限,java,java-8,java-stream,Java,Java 8,Java Stream,如何获取记录,哪些计数总和应在限制范围内。在下面的示例中,有记录对象包含recordId和count,我想根据count的总和获取记录数据,该总和应小于或等于我的限制条件 公共类记录{ 私有int-recordID; 私人整数计数; 公共记录(整数记录ID、整数计数){ this.recordID=recordID; this.count=计数; } public int getRecordID(){ 返回recordID; } 公共无效setRecordID(int-recordID){ th
记录
对象包含recordId和count,我想根据count的总和获取记录数据,该总和应小于或等于我的限制条件
公共类记录{
私有int-recordID;
私人整数计数;
公共记录(整数记录ID、整数计数){
this.recordID=recordID;
this.count=计数;
}
public int getRecordID(){
返回recordID;
}
公共无效setRecordID(int-recordID){
this.recordID=recordID;
}
public int getCount(){
返回计数;
}
公共无效集合计数(整数计数){
this.count=计数;
}
}
公共静态void main(字符串[]args){
最终列表记录列表=新的ArrayList();
记录列表。添加(新记录(100,10));
记录列表。添加(新记录(501,20));
记录列表。添加(新记录(302,5));
记录列表。添加(新记录(405,2));
记录列表。添加(新记录(918,8));
整数极限=35;
}
预期结果
recordList
应该有记录对象:[100,10],[500,20],[302,5]记录使用流API解决这一问题的问题是,您必须将一些信息保留在处理上下文之外,并同时对其进行读取/更新(依赖)。这些任务不适用于流API
使用一个适用于此的for循环:
int index = 0; // highest index possible
int sum = 0; // sum as a temporary variable
for (int i=0; i<recordList.size(); i++) { // for each Record
sum += recordList.get(i).getCount(); // ... add the 'count' to the 'sum'
if (sum <= limit) { // ... until the sum is below the limit
index = i; // ... move the pivot
} else break; // ... or else stop processing
}
// here you need to get the list from 0 to index+1
// as long as the 2nd parameter of subList(int, int) is exlcusive
List<Record> filteredRecords = recordList.subList(0, index + 1);
int index=0;//可能的最高索引
整数和=0;//sum作为临时变量
对于(int i=0;i这是我唯一能想到的事情,但它没有常规循环那么有效,因为它为它拥有的每个列表项运行。这也会导致它进一步向下添加其他值。例如,如果limit为46,则将跳过计数为5的第三个项,但下一个计数为2的项仍将被添加。不知道这是否为i这是你想要的行为
AtomicInteger count = new AtomicInteger();
recordList = recordList.stream().filter(r -> {
if(count.get() + r.count <= limit){
count.addAndGet(r.count);
return true;
}
return false;
}).collect(Collectors.toList());
AtomicInteger count=新的AtomicInteger();
recordList=recordList.stream().filter(r->{
如果(count.get()+r.count将以下toString
添加到类中以进行打印,则可以按如下操作:
public String toString() {
return String.format("[%s, %s]", recordID, count);
}
- 分配一个列表来存储结果
- 初始化总和
- 遍历列表,对计数求和,直到
达到临界点
使用java 8,您可以执行以下操作:
public static void main(String[] args) {
int limit = 35;
List<Records> recordList = new ArrayList<>();
recordList.add(new Records(100, 10));
recordList.add(new Records(501, 20));
recordList.add(new Records(302, 5));
recordList.add(new Records(405, 2));
recordList.add(new Records(918, 8));
List<Records> limitedResult = recordList.stream().filter(new Predicate<Records>() {
int sum = 0;
@Override
public boolean test(Records records) {
sum=sum+records.getCount();
return sum <= limit;
}
}).collect(Collectors.toList());
//do what do you want with limitedResult
System.out.println(limitedResult);
}
我认为流操作不适合这种情况。老式的while
循环就可以了。函数编程中的函数(流使用)被认为是无状态的。您的任务要求您记住一个状态。只需使用常规循环,这里没有流的好处。@f1sh在正确的函数式编程中,这将是一个前缀扫描操作,后跟一个zip和一个“take while”。问题是流只读取一次抽象。这是这里的问题,而不是函数式编程。也就是说,它仍然可以作为缩减或收集器来完成。我从这次讨论中学到了很多东西!下面的帖子可能也会有所帮助(我不认为它是重复的,因为它更一般)-你可能会发现这很有趣:)这并不能保证工作,因为谓词等根据契约是无状态的。流可能会无序消费等。只有收集器才允许有状态。
[100, 10]
[501, 20]
[302, 5]
public static void main(String[] args) {
int limit = 35;
List<Records> recordList = new ArrayList<>();
recordList.add(new Records(100, 10));
recordList.add(new Records(501, 20));
recordList.add(new Records(302, 5));
recordList.add(new Records(405, 2));
recordList.add(new Records(918, 8));
List<Records> limitedResult = recordList.stream().filter(new Predicate<Records>() {
int sum = 0;
@Override
public boolean test(Records records) {
sum=sum+records.getCount();
return sum <= limit;
}
}).collect(Collectors.toList());
//do what do you want with limitedResult
System.out.println(limitedResult);
}
//Reusable predicate
public static Predicate<Records> limitRecordPredicate(int limit){
return new Predicate<Records>() {
int sum = 0;
@Override
public boolean test (Records records){
sum = sum + records.getCount();
return sum <= limit;
}
};
}
List<Records> limitedResult = recordList.stream().filter(limitRecordPredicate(limit)).collect(Collectors.toList());
//do what do you want with limitedResult
System.out.println(limitedResult);
[Records[recordID=100, count=10], Records[recordID=501, count=20], Records[recordID=302, count=5]]