基于比特位图映射对List<Object>多维度排序

简介:程序实现了基于位图编码的多维度商品排序。代码将商品的四个维度(置顶、学生专享、排序值、库存)编码到一个64位长整型中,通过数值比较实现复合排序。

主要特点:

  1. 创新编码方案‌:使用位运算将布尔值和整数统一编码,最高位表示置顶,次高位表示学生专享
  2. 优先级保证‌:编码结构确保isTop > isStudent > sort > store的优先级顺序
  3. 性能优化‌:一次编码后使用快速排序,适合大规模数据
  4. 结果验证‌:与传统比较器方法对比,确保排序正确性
  5. 可扩展性‌:编码方案可以轻松调整各字段的位数分配

这种方法结合了位图排序的思想,同时解决了多维度排序的复杂性问题。

java 复制代码
/**
 * 商品实体类
 */
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; }

    @Override
    public 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%左右。循环越多,维度越多,优化效果越明显;

相关推荐
霸道流氓气质6 小时前
Java中使用Collator实现对象List按照中文姓名属性进行A-Z的排序实现
java·开发语言·list
Mr.H01276 小时前
克鲁斯卡尔(Kruskal)算法
数据结构·算法·图论
熬了夜的程序员7 小时前
【LeetCode】94. 二叉树的中序遍历
数据结构·算法·leetcode·职场和发展·深度优先
熬了夜的程序员7 小时前
【LeetCode】92. 反转链表 II
数据结构·算法·leetcode·链表·职场和发展·排序算法
头发还没掉光光7 小时前
Linux多线程之生产消费模型,日志版线程池
linux·运维·开发语言·数据结构·c++
laocooon5238578868 小时前
一个蛇形填充n×n矩阵的算法
数据结构·算法
岑梓铭8 小时前
《考研408数据结构》第六章(5.4树和森林)复习笔记
数据结构·笔记·考研·算法·408·ds
景早8 小时前
力扣1. 两数之和
数据结构·算法·leetcode
Miraitowa_cheems17 小时前
LeetCode算法日记 - Day 88: 环绕字符串中唯一的子字符串
java·数据结构·算法·leetcode·深度优先·动态规划