本文目录导读:

Java权重排序实现方案
权重排序的核心思想是为每个元素分配一个权重值,然后根据权重对元素进行排序,以下是几种常见的实现方式:
基础对象排序(实现Comparable接口)
import java.util.*;
// 定义带权重的实体类
class WeightedItem implements Comparable<WeightedItem> {
private String name;
private double weight; // 权重值
public WeightedItem(String name, double weight) {
this.name = name;
this.weight = weight;
}
// 实现Comparable接口,定义排序规则(降序排列)
@Override
public int compareTo(WeightedItem other) {
// 降序排列:权重大的排在前面
return Double.compare(other.weight, this.weight);
}
// getter/setter方法
public String getName() {
return name;
}
public double getWeight() {
return weight;
}
@Override
public String toString() {
return String.format("Item{name='%s', weight=%.2f}", name, weight);
}
}
// 使用示例
public class WeightSortExample1 {
public static void main(String[] args) {
List<WeightedItem> items = new ArrayList<>();
items.add(new WeightedItem("A", 3.5));
items.add(new WeightedItem("B", 1.2));
items.add(new WeightedItem("C", 5.8));
items.add(new WeightedItem("D", 2.1));
System.out.println("排序前:" + items);
Collections.sort(items);
System.out.println("排序后:" + items);
}
}
使用Comparator进行自定义排序
import java.util.*;
class Item {
private String id;
private int priority; // 优先级权重
private double score; // 分数权重
private Date createTime; // 时间权重
public Item(String id, int priority, double score, Date createTime) {
this.id = id;
this.priority = priority;
this.score = score;
this.createTime = createTime;
}
// 计算综合权重(可根据业务需求定制)
public double getCompositeWeight() {
return priority * 0.5 + score * 0.3 + (1000 - createTime.getTime() % 1000) * 0.2;
}
// getter方法
public String getId() { return id; }
public int getPriority() { return priority; }
public double getScore() { return score; }
public Date getCreateTime() { return createTime; }
@Override
public String toString() {
return String.format("Item{id='%s', priority=%d, score=%.2f}",
id, priority, score);
}
}
public class WeightSortExample2 {
public static void main(String[] args) {
List<Item> items = new ArrayList<>();
items.add(new Item("001", 3, 85.5, new Date()));
items.add(new Item("002", 1, 92.0, new Date(System.currentTimeMillis() - 3600000)));
items.add(new Item("003", 5, 78.3, new Date(System.currentTimeMillis() - 7200000)));
items.add(new Item("004", 2, 88.9, new Date(System.currentTimeMillis() - 1800000)));
System.out.println("排序前:");
items.forEach(System.out::println);
// 多权重综合排序
items.sort(Comparator
.comparingDouble(Item::getPriority).reversed() // 优先按优先级降序
.thenComparingDouble(Item::getScore).reversed() // 再按分数降序
.thenComparing(Item::getCreateTime) // 最后按时间升序
);
System.out.println("\n排序后:");
items.forEach(System.out::println);
// 使用综合权重排序
items.sort(Comparator.comparingDouble(Item::getCompositeWeight).reversed());
System.out.println("\n综合权重排序后:");
items.forEach(System.out::println);
}
}
随机权重排序(常用于抽奖等场景)
import java.util.*;
class LotteryItem implements Comparable<LotteryItem> {
private String name;
private double weight; // 中奖概率权重
public LotteryItem(String name, double weight) {
this.name = name;
this.weight = weight;
}
public String getName() { return name; }
public double getWeight() { return weight; }
@Override
public int compareTo(LotteryItem other) {
return Double.compare(other.weight, this.weight);
}
}
public class WeightedRandomSelector {
private List<LotteryItem> items;
private double totalWeight;
private Random random = new Random();
public WeightedRandomSelector(List<LotteryItem> items) {
this.items = new ArrayList<>(items);
this.totalWeight = items.stream()
.mapToDouble(LotteryItem::getWeight)
.sum();
}
// 按权重随机选择一个元素
public LotteryItem select() {
double rand = random.nextDouble() * totalWeight;
double cumulativeWeight = 0;
for (LotteryItem item : items) {
cumulativeWeight += item.getWeight();
if (rand <= cumulativeWeight) {
return item;
}
}
// 默认返回最后一个(理论上不会执行到这里)
return items.get(items.size() - 1);
}
// 按权重排序后返回所有元素
public List<LotteryItem> getSortedItems() {
List<LotteryItem> sorted = new ArrayList<>(items);
Collections.sort(sorted);
return sorted;
}
public static void main(String[] args) {
List<LotteryItem> lotteries = Arrays.asList(
new LotteryItem("一等奖", 0.1),
new LotteryItem("二等奖", 0.2),
new LotteryItem("三等奖", 0.3),
new LotteryItem("参与奖", 0.4)
);
WeightedRandomSelector selector = new WeightedRandomSelector(lotteries);
// 模拟多次抽奖
Map<String, Integer> countMap = new HashMap<>();
for (int i = 0; i < 10000; i++) {
LotteryItem selected = selector.select();
countMap.merge(selected.getName(), 1, Integer::sum);
}
System.out.println("10000次抽奖结果统计:");
countMap.forEach((key, value) ->
System.out.printf("%s: %d次 (%.2f%%)\n", key, value, value / 100.0));
System.out.println("\n按权重排序后的奖项:");
selector.getSortedItems().forEach(item ->
System.out.printf("%s (权重: %.2f)\n", item.getName(), item.getWeight()));
}
}
多维度权重评分排序
import java.util.*;
import java.util.stream.Collectors;
class Product {
private String name;
private double salesVolume; // 销量
private double rating; // 评价分数
private double price; // 价格(越低越好)
private double freshness; // 新鲜度(0-1)
public Product(String name, double salesVolume, double rating,
double price, double freshness) {
this.name = name;
this.salesVolume = salesVolume;
this.rating = rating;
this.price = price;
this.freshness = freshness;
}
// 计算综合权重分数(可配置权重系数)
public double calculateScore(double salesWeight, double ratingWeight,
double priceWeight, double freshnessWeight) {
// 价格取反(价格越低得分越高)
double priceScore = 1.0 / (1 + price / 100);
return salesVolume * salesWeight +
rating * ratingWeight +
priceScore * priceWeight +
freshness * freshnessWeight;
}
public String getName() { return name; }
@Override
public String toString() {
return String.format("Product{name='%s', sales=%.0f, rating=%.1f, price=%.2f}",
name, salesVolume, rating, price);
}
}
public class MultiWeightSorter {
private double salesWeight = 0.3;
private double ratingWeight = 0.3;
private double priceWeight = 0.2;
private double freshnessWeight = 0.2;
public MultiWeightSorter() {}
public MultiWeightSorter(double salesWeight, double ratingWeight,
double priceWeight, double freshnessWeight) {
this.salesWeight = salesWeight;
this.ratingWeight = ratingWeight;
this.priceWeight = priceWeight;
this.freshnessWeight = freshnessWeight;
}
public List<Product> sortProducts(List<Product> products) {
return products.stream()
.sorted(Comparator.comparingDouble(
p -> -p.calculateScore(salesWeight, ratingWeight,
priceWeight, freshnessWeight)))
.collect(Collectors.toList());
}
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product("手机A", 10000, 4.5, 2999, 0.9));
products.add(new Product("手机B", 8000, 4.8, 3999, 0.85));
products.add(new Product("手机C", 15000, 4.2, 1999, 0.7));
products.add(new Product("手机D", 12000, 4.6, 2499, 0.95));
System.out.println("排序前:");
products.forEach(System.out::println);
MultiWeightSorter sorter = new MultiWeightSorter(0.4, 0.3, 0.2, 0.1);
List<Product> sortedProducts = sorter.sortProducts(products);
System.out.println("\n排序后(销量权重0.4,评价权重0.3,价格权重0.2,新鲜度权重0.1):");
sortedProducts.forEach(System.out::println);
}
}
最佳实践建议
-
选择合适的排序方式
- 单一权重:实现
Comparable接口 - 多权重排序:使用
Comparator链式调用 - 随机权重选择:使用概率累加算法
- 单一权重:实现
-
性能优化注意事项
- 对于大型数据集,考虑使用
parallelStream()进行并行处理 - 避免在排序过程中频繁计算权重值
- 如果需要保持有序状态,使用
TreeSet或PriorityQueue
- 对于大型数据集,考虑使用
-
权重归一化处理
- 确保不同量级的权重能够合理比较
- 可以对原始数据进行归一化处理(如:z-score标准化、min-max标准化)
-
实际应用场景
- 搜索引擎结果排序
- 推荐系统物品排序
- 任务优先级调度
- 广告竞价排名
- 游戏道具概率抽取
选择哪种实现方式取决于你的具体业务需求和数据规模。