当前基于双重奖品的方法。
partial_fit()
购物基本上是一张地图:public Map<String, BigDecimal> averageProductPriceInCategory() {
return shopping.entrySet()
.stream()
.flatMap(e -> e.getValue().keySet().stream())
.collect(Collectors.groupingBy(Product::getCategory,
Collectors.averagingDouble(Product::getPrize)));
}
,
以下代码段仅可用于计算属于指定类别的产品的总奖金。不确定如何使用BigDecimals计算有关类别的平均产品奖励
Map<Client, Map<Product,Integer>>
答案 0 :(得分:2)
看看如何实现Collectors.averagingDouble
或Collectors.averagingInt
。
// Register Action
exports.register = (req, res) => {
function getAvailableFunds() {
const availableFunds = 0;
return availableFunds;
}
async function getAccountBill() {
const accountBill = `2222${Math.floor(
Math.random() * 90000000000000000000,
) + 10000000000000000000}`;
try {
const isAccountBill = await Bill.findOne({
where: {
account_bill: accountBill,
},
});
return isAccountBill ? await getAccountBill() : accountBill;
} catch(e) {
console.error(e);
}
}
function getAccountBalanceHistory() {
const accountBalanceHistory = '0,0';
return accountBalanceHistory;
}
function getTodayDate() {
const today = new Date();
return today;
}
User.findOne({
where: { login: req.body.login },
}).then(isUser => {
if (!isUser) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
req.body.password = hash;
const user = await User.create({
login: req.body.login,
password: req.body.password,
name: req.body.name,
surname: req.body.surname,
email: req.body.email,
date_registration: getTodayDate(),
});
const account_bill = await getAccountBill();
const bill = await Bill.create({
id_owner: user.id,
account_bill,
available_funds: getAvailableFunds(),
})
const additional = await Additional.create({
id_owner: user.id,
account_balance_history: getAccountBalanceHistory(),
});
res.status(200).json({ register: true });
}),
);
});
} else {
res.status(400).json({ error: 'User already exists.' });
}
});
};
从本质上讲,您需要一种可变的累积类型,该类型将包含public static <T> Collector<T, ?, Double>
averagingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<>(
() -> new long[2],
(a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
}
(这是产品价格的总和)和BigDecimal
(这是已处理的许多产品)。有了这些,问题就归结为编写简单的Collector<Product, AccumulationType, BigDecimal>
。
我简化了一个示例,并删除了getters / setter和一个全参数的构造函数。除了嵌套类int
,您还可以对2个元素使用任何可变的holder类。
ProductPriceSummary
答案 1 :(得分:0)
出于理解目的,我将操作分为两个步骤。如果您愿意,可以将两个步骤结合在一起。
Map<String, BigDecimal[]> stringMap = shopping.entrySet()
.stream()
.flatMap(e -> e.getValue().keySet().stream())
.collect(Collectors.groupingBy(Product::getCategory,Collectors.collectingAndThen(Collectors.toList(),l -> l.stream().map(Product::getPrize)
.map(bd -> new BigDecimal[]{bd, BigDecimal.ONE})
.reduce((a, b) -> new BigDecimal[]{a[0].add(b[0]), a[1].add(BigDecimal.ONE)})
.get()
)));
Map<String, BigDecimal> stringBigDecimalMap = stringMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,e -> e.getValue()[0].divide(e.getValue()[1])));
说明:
a
的{{1}}值在第一个元素中具有部分和,在第二个元素中具有部分计数。 (a,b)
元素的第一个元素包含要添加到总和的每个BigDecimal值。 b
的第二个元素未使用。b
答案 2 :(得分:0)
这基于[Double|Int]Pipeline.average()
的源代码。它使用数组存储项目数(在索引0
处)和总和(在索引1
处)。
public Map<String, BigDecimal> averageProductPriceInCategory() {
return shopping.entrySet().stream()
.flatMap(entry -> entry.getValue().keySet().stream())
.collect(Collectors.groupingBy(
Product::getCategory,
Collector.of(
() -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
(array, product) -> {
array[0] = array[0].add(BigDecimal.ONE);
array[1] = array[1].add(product.getPrice());
},
(left, right) -> {
left[0] = left[0].add(right[0]);
left[1] = left[1].add(right[1]);
return left;
},
array -> array[0].compareTo(BigDecimal.ONE) <= 0
? array[1]
: array[1].divide(array[0], RoundingMode.HALF_UP)
)
));
}
这有一些缺点:
BigDecimal
,使用int
或long
会更有意义。可以通过将收集器提取到自定义类中来解决这些问题(就像Andrew's answer一样。)
答案 3 :(得分:0)
您可以像这样创建自己的收集器:
Collector<BigDecimal, BigDecimal[], BigDecimal> avgCollector = Collector.of(
() -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
(pair, val) -> {
pair[0] = pair[0].add(val);
pair[1] = pair[1].add(BigDecimal.ONE);
},
(pair1, pair2) -> new BigDecimal[]{pair1[0].add(pair2[0]), pair1[1].add(pair2[1])},
(pair) -> pair[0].divide(pair[1], 2, RoundingMode.HALF_UP)
);
...然后使用它:
Map<String, BigDecimal> totalProductPriceInEachCategory = shopping.values().stream()
.flatMap(e -> e.keySet().stream())
.collect(groupingBy(Product::getCategory, mapping(Product::getPrice, avgCollector)));