基于比特位图映射对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%左右。循环越多,维度越多,优化效果越明显;

相关推荐
又是忙碌的一天28 分钟前
二叉树的构建与增删改查(2) 删除节点
数据结构
Code Slacker42 分钟前
LeetCode Hot100 —— 滑动窗口(面试纯背版)(四)
数据结构·c++·算法·leetcode
F_D_Z2 小时前
最长连续序列(Longest Consecutive Sequence)
数据结构·算法·leetcode
WolfGang0073212 小时前
代码随想录算法训练营Day50 | 拓扑排序、dijkstra(朴素版)
数据结构·算法
一直都在5723 小时前
数据结构入门:二叉排序树的删除算法
数据结构·算法
hweiyu003 小时前
排序算法简介及分类
数据结构
oscar9993 小时前
CSP-J教程——第二阶段第十二、十三课:排序与查找算法
数据结构·算法·排序算法
fei_sun4 小时前
【总结】【OS】成组链接法
jvm·数据结构
月明长歌4 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
保持低旋律节奏4 小时前
数据结构——链表自实现
数据结构·链表