基于比特位图映射对List<Object>多维度排序
简介:程序实现了基于位图编码的多维度商品排序。代码将商品的四个维度(置顶、学生专享、排序值、库存)编码到一个64位长整型中,通过数值比较实现复合排序。
主要特点:
- 创新编码方案:使用位运算将布尔值和整数统一编码,最高位表示置顶,次高位表示学生专享
- 优先级保证:编码结构确保isTop > isStudent > sort > store的优先级顺序
- 性能优化:一次编码后使用快速排序,适合大规模数据
- 结果验证:与传统比较器方法对比,确保排序正确性
- 可扩展性:编码方案可以轻松调整各字段的位数分配
这种方法结合了位图排序的思想,同时解决了多维度排序的复杂性问题。
/*** 商品实体类*/
class Product {private String name;private Integer sort;      // 排序字段private Integer store;     // 库存private Boolean isTop;     // 是否置顶private Boolean isStudent; // 是否学生专享public Product(String name, Integer sort, Integer store, Boolean isTop, Boolean isStudent) {this.name = name;this.sort = sort;this.store = store;this.isTop = isTop;this.isStudent = isStudent;}public String getName() { return name; }public Integer getSort() { return sort; }public Integer getStore() { return store; }public Boolean getIsTop() { return isTop; }public Boolean getIsStudent() { return isStudent; }@Overridepublic String toString() {return String.format("商品:%-8s 置顶:%-5s 学生:%-5s 排序值:%-3d 库存:%-3d", name, isTop, isStudent, sort, store);}
}/*** 基于位图编码的商品排序器*/
class ProductBitmapSorter {// 位分配方案(从高位到低位)private static final int TOP_BIT_SHIFT = 60;      // 1位: 置顶标识private static final int STUDENT_BIT_SHIFT = 58;  // 1位: 学生专享标识private static final int SORT_BIT_SHIFT = 40;     // 18位: 排序字段private static final int STORE_BIT_SHIFT = 20;    // 20位: 库存字段/*** 将商品的多维属性编码为一个长整型* 编码格式:[1位置顶][1位学生][18位排序值][20位库存]*/public static long encodeProduct(Product product) {long encoded = 0L;// 置顶标识(最高位)if (Boolean.TRUE.equals(product.getIsTop())) {encoded |= (1L << TOP_BIT_SHIFT);}// 学生专享标识if (Boolean.TRUE.equals(product.getIsStudent())) {encoded |= (1L << STUDENT_BIT_SHIFT);}// 排序字段(限制在0-262143范围内)int sortValue = Math.min(Math.max(product.getSort(), 0), 262143);encoded |= ((long) sortValue) << SORT_BIT_SHIFT;// 库存字段(限制在0-1048575范围内)int storeValue = Math.min(Math.max(product.getStore(), 0), 1048575);encoded |= ((long) storeValue) << STORE_BIT_SHIFT;return encoded;}/*** 使用位图编码进行排序*/public static void sortProductsWithBitmap(List<Product> products) {// 创建编码映射Map<Long, Product> encodedMap = new HashMap<>();List<Long> encodedValues = new ArrayList<>();// 编码所有商品for (Product product : products) {long encoded = encodeProduct(product);encodedMap.put(encoded, product);encodedValues.add(encoded);}// 对编码值进行排序(自然降序)Collections.sort(encodedValues, Collections.reverseOrder());// 清空原列表并按排序后的编码重新填充products.clear();for (Long encoded : encodedValues) {products.add(encodedMap.get(encoded));}}/*** 传统的比较器排序(用于对比验证)*/public static void sortProductsTraditional(List<Product> products) {Collections.sort(products, (p1, p2) -> {// 第一优先级: isTop (置顶的排在前面)int topCompare = Boolean.compare(p2.getIsTop(), p1.getIsTop());if (topCompare != 0) return topCompare;// 第二优先级: isStudent (学生专享排在前面)int studentCompare = Boolean.compare(p2.getIsStudent(), p1.getIsStudent());if (studentCompare != 0) return studentCompare;// 第三优先级: sort字段 (数值大的排在前面)int sortCompare = Integer.compare(p2.getSort(), p1.getSort());if (sortCompare != 0) return sortCompare;// 第四优先级: store库存 (库存多的排在前面)return Integer.compare(p2.getStore(), p1.getStore());});}/*** 解码长整型为可读格式(用于调试)*/public static String decodeProduct(long encoded) {boolean isTop = ((encoded >> TOP_BIT_SHIFT) & 1) == 1;boolean isStudent = ((encoded >> STUDENT_BIT_SHIFT) & 1) == 1;int sortValue = (int) ((encoded >> SORT_BIT_SHIFT) & 0x3FFFF); // 18位掩码int storeValue = (int) ((encoded >> STORE_BIT_SHIFT) & 0xFFFFF); // 20位掩码return String.format("置顶:%-5s 学生:%-5s 排序值:%-6d 库存:%-6d", isTop, isStudent, sortValue, storeValue);}
}/*** 演示主类*/
public class ProductBitmapSort {public static void main(String[] args) {// 创建测试商品数据List<Product> products = Arrays.asList(new Product("商品A", 10, 100, false, true),new Product("商品B", 20, 50, true, false),new Product("商品C", 15, 200, true, true),new Product("商品D", 25, 80, false, false),new Product("商品E", 10, 150, false, true),new Product("商品F", 30, 300, false, false),new Product("商品G", 5, 60, true, false));System.out.println("=== 原始商品列表 ===");printProducts(products);// 方法1: 位图编码排序List<Product> bitmapSorted = new ArrayList<>(products);ProductBitmapSorter.sortProductsWithBitmap(bitmapSorted);System.out.println("\n=== 位图编码排序结果 ===");printProducts(bitmapSorted);// 方法2: 传统比较器排序(用于验证)List<Product> traditionalSorted = new ArrayList<>(products);ProductBitmapSorter.sortProductsTraditional(traditionalSorted);System.out.println("\n=== 传统比较器排序结果 ===");printProducts(traditionalSorted);// 验证两种方法结果是否一致boolean isSame = true;for (int i = 0; i < bitmapSorted.size(); i++) {if (!bitmapSorted.get(i).getName().equals(traditionalSorted.get(i).getName())) {isSame = false;break;}}System.out.println("\n=== 排序验证 ===");System.out.println("位图排序与传统排序结果是否一致: " + isSame);// 显示编码示例System.out.println("\n=== 编码示例 ===");for (Product product : products) {long encoded = ProductBitmapSorter.encodeProduct(product);System.out.println(product.getName() + " -> 编码值: " + encoded + " -> 解码: " + ProductBitmapSorter.decodeProduct(encoded));}}private static void printProducts(List<Product> products) {for (int i = 0; i < products.size(); i++) {System.out.println((i + 1) + ". " + products.get(i));}}
}总结:
相对于传统的javaAPI排序,性能优化在50%左右。循环越多,维度越多,优化效果越明显;
