java bitmap jar_Java面试中常用的BitMap代码

引言

阿里内推面试的时候被考了一道编程题:10亿个范围为1~2048的整数,将其去重并计算数字数目。

我看到这个题目就想起来了《编程珠玑》第一章讲的叫做BitMap的数据结构,但是我并没有在java上实现过,这就比较尴尬了,再加上时间不多了,只好暂时用byte代替bit,浪费7个字节,在这篇文章里总结一下BitMap的常用代码,以免重蹈覆辙。

偷懒的方法

其实java.util包中已经有了一个实现,可以用这个数据结构偷懒,写了一个Demo如下:

package org.du.offerproblem.bitmap;

import java.util.BitSet;

/**

* Created by 燃烧杯 on 2018/2/24.

*/

public class BitSetTest {

public static void main(String[] args) {

int [] array = new int [] {1,2,3,22,0,3,63};

BitSet bitSet = new BitSet(1);

System.out.println(bitSet.size()); //64

bitSet = new BitSet(65);

System.out.println(bitSet.size()); //128

bitSet = new BitSet(23);

System.out.println(bitSet.size()); //64

//将数组内容组bitmap

for(int i=0;i

{

bitSet.set(array[i], true);

}

System.out.println(bitSet.get(22));

System.out.println(bitSet.get(60));

System.out.println("下面开始遍历BitSet:");

for ( int i = 0; i < bitSet.size(); i++ ){

System.out.println(bitSet.get(i));

}

}

}

java.util.BitSet的底层是long数组,.size()方法返回的是BitSet当前位数,因为long是64位的,所以size返回的值也是64的整数倍,所以在上面的代码中发现,我在构造函数中传入初始化长度1~64中的任意一个值,size的大小都是64位,因为此时long数组的长度只有1,而我一旦将其设置成65,size的大小就变成128了。

用这个类是个偷懒的好办法,但是一旦面试官一定要让你自己实现一个就不行了。

自己实现BitMap

可以用int数组来实现一个BitMap,这种方法最关键的是求出index在int数组中的位置以及在该位置上的偏移量,有如下公式:

int数组中的位置(belowIndex) = (index - 1) >> 5

偏移量(offset) = (index - 1) & 31

我们这里假设index是从1开始的,所以先将index减去1,如果你要统计的数据范围是从0开始的,则不需要减去这个1。右移5位(相当于除以32)的原因是,一个int型数据是32位的(2的5次方等于32)。偏移量中&31相当于模32,其原因也因为int型数据是32位的。如果你不准备基于int,而是准备基于其他的,如byte,long的话,(以byte为例)则将>>5改成>>3,&31改成&7即可。

setBit的流程如下:

求出belowIndex并且得到int值;

求出offset并且利用“或运算”将刚才得到的int值的offset位置置为1;

getBit的流程如下:

求出belowIndex并且得到int值;

求出offset,之后利用“与运算”取出offset位置的值将其变为01后返回;

代码如下:

package org.du.offerproblem.bitmap;

/**

* 实现BitMap

*注:这个bitMap的index是从1开始的

*/

public class BitMap {

private long length;

private static int[] bitsMap;

//构造函数中传入数据中的最大值

public BitMap(long length) {

this.length = length;

// 根据长度算出,所需数组大小

bitsMap = new int[(int) (length >> 5) + ((length & 31) > 0 ? 1 : 0)];

}

public int getBit(long index) {

int intData = bitsMap[(int) ((index - 1) >> 5)];

int offset = (int) ((index - 1) & 31);

return intData >> offset & 0x01;

}

public void setBit(long index) {

// 求出该index - 1所在bitMap的下标

int belowIndex = (int) ((index - 1) >> 5);

// 求出该值的偏移量(求余)

int offset = (int) ((index - 1) & 31);

int inData = bitsMap[belowIndex];

bitsMap[belowIndex] = inData | (0x01 << offset);

}

public static void main(String[] args) {

BitMap bitMap = new BitMap(32);

bitMap.setBit(32);

System.out.println(bitMap.getBit(1));

System.out.println(bitMap.getBit(32));

}

}

使用BitMap进行数据去重

下面给出数组去重的代码:

package org.du.offerproblem.bitmap;

import java.util.Arrays;

/**

* Created by 燃烧杯 on 2018/2/24.

* 这个BitMap的去重是从0开始

*/

public class BitMapRepRemove {

//public static final int _1MB = 1024 * 1024;

//public static byte[] flags = new byte[ 512 * _1MB ];

public static byte[] flags;

public static void main(String[] args) {

int[] array = {255, 1024, 1024, 0, 65536, 0, 1024, 8888, 9999, 1111, 8888};

int length = 65536 + 1;

flags = new byte[(int) (length >> 3) + ((length & 7) > 0 ? 1 : 0)];

int index = 0;

for(int num : array) {

if( getFlags(num) != 1) {

//未出现的元素

array[index] = num;

index = index + 1;

//设置标志位

setFlags(num);

}

}

array = Arrays.copyOf(array, index);

System.out.println(Arrays.toString(array));

System.out.println(array.length);

}

public static void setFlags(int num) {

int offset = num & (0x07);

flags[num >> 3] |= 0x01 << offset;

}

public static int getFlags(int num) {

int offset = num & (0x07);

return flags[num >> 3] >> offset & 0x01;

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/395804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动端工程架构与后端工程架构的思想摩擦之旅(1)

此文已由作者黎星授权网易云社区发布。欢迎访问网易云社区&#xff0c;了解更多网易技术产品运营经验记资源投放后端工程的架构调整与优化 架构思考一直以来对软件工程架构有着极大的兴趣&#xff0c;无论是之前负责的移动端Android工程&#xff0c;亦或是现在转到后端开发后维…

View野指针问题分析报告

【问题描述】 音乐组同事反馈了一个必现Native Crash问题&#xff0c;tombstone如下&#xff1a; pid: 5028, tid: 5028, name: com.miui.player >>> com.miui.player <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 79801f28r0 7ac59c98 r1 …

SicilyFunny Game

一、题目描述 Two players, Singa and Suny, play, starting with two natural numbers. Singa, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be non…

java 分布式同步_Java Web分布式集群搭建(三)——Session同步

对于一个业务系统的Tomcat集群来说&#xff0c;必须保证同一个用户访问到任一台服务器上都可以维持之前操作的身份。比如在服务器A进行了登陆&#xff0c;那么在服务器B中也要同步该用户已登录的状态&#xff0c;这里就用到了Session的同步。同步方式sticky模式、复制模式、Ter…

移动应用程序和网页应用程序_如何不完全破坏您的移动应用程序的用户界面

移动应用程序和网页应用程序by Luke Konior卢克科尼尔(Luke Konior) 如何不完全破坏您的移动应用程序的用户界面 (How to not utterly ruin your mobile app’s user interface) There’s no single universal formula for designing a great user interface (if you discover…

logging记录日志

日志是一个系统的重要组成部分&#xff0c;用以记录用户操作、系统运行状态和错误信息。日志记录的好坏直接关系到系统出现问题时定位的速度。logging模块Python2.3版本开始成为Python标准库的一部分。 日志级别 在最简单的使用中&#xff0c;我们直接导入logging模块&#xff…

C#编程之接口

1.定义 接口是把公共方法和属性组合起来&#xff0c;以封装特定功能的一个集合。&#xff08;一旦定义了接口&#xff0c;就可以在类中实现它。这样类就可以支持接口所指定的所有属性和成员&#xff09; 注意1&#xff1a;接口不能单独存在。不能像实例化一个类那样实例化一个接…

supervisor守护进程

2019独角兽企业重金招聘Python工程师标准>>> supervisor 是一个client/server系统,把不是守护进程的进程变成守护进程,并监控和控制类 Unix 操作系统上的进程。 upervisor就是用Python开发的一套通用的进程管理程序&#xff0c;能将一个普通的命令行进程变为后台dae…

神经网络算法 java 源代码_神经网络算法与实现 ——基于Java语言 代码实例

【实例简介】Neural Network Programming with Java_ISBN 978-7-115-46093-6【实例截图】【核心代码】NeuralNetworkProgrammingwithJava_code└── Neural Network Programming with Java_code├── Chapter1│ ├── HiddenLayer.java│ ├── InputLayer.java│ ├…

javascript面试_在编码面试中需要注意的3个JavaScript问题

javascript面试JavaScript is the official language of all modern web browsers. As such, JavaScript questions come up in all sorts of developer interviews.JavaScript是所有现代Web浏览器的官方语言。 因此&#xff0c;各种开发人员访谈中都会出现JavaScript问题。 T…

【学习笔记】深入理解js原型和闭包(11)——执行上下文栈

继续上文的内容。 执行全局代码时&#xff0c;会产生一个执行上下文环境&#xff0c;每次调用函数都又会产生执行上下文环境。当函数调用完成时&#xff0c;这个上下文环境以及其中的数据都会被消除&#xff0c;再重新回到全局上下文环境。处于活动状态的执行上下文环境只有一个…

Java基础--访问权限控制符

今天我们来探讨一下访问权限控制符。 使用场景一&#xff1a;攻城狮A编写了ClassA&#xff0c;但是他不想所有的攻城狮都可以使用该类&#xff0c;应该怎么办&#xff1f; 使用场景二&#xff1a;攻城狮A编写了ClassA&#xff0c;里面有func1方法和func2方法&#xff0c;但是他…

css绘制正方体_设计师仅使用CSS绘制了8个标志性X战警

css绘制正方体Here are three links worth your time:这是三个值得您花费时间的链接&#xff1a; A designer drew 8 iconic X-Men using nothing but CSS (1 minute interactive) 一位设计师仅用CSS绘制了8个标志性的X战警( 互动时间为1分钟 ) Raspberry Pi just turned 5. H…

Dubbo简单介绍及实例

1、概念 Dubbo是一个分布式服务框架&#xff0c;以及阿里巴巴内部的SOA服务化治理方案的核心框架。其功能主要包含&#xff1a;高性能NIO通讯及多协议集成。服务动态寻址与路由。软负载均衡与容错&#xff0c;依赖分析与降级等。 说通俗点&#xff0c;就是首先将程序组件化成一…

Oracle 10.2.0.5升级至11.2.0.4

参照MOS 官方文档Complete Checklist for Manual Upgrade to Oracle Database 11gR2 (11.2) (Doc ID 837570.1)一、升级前的准备1、复制utlu112i.sql脚本从11G数据库复制$ORACLE_HOME/rdbms/admin/utlu112i.sql 脚本至10g 数据库临时目录&#xff0c;准备执行如果不在10g数据库…

脱壳_详细_使用的方法_01

ZC: 如何确定被调试程序已经来到了 未加壳的程序中&#xff1f; ZC:  视频中是使用判断集中语言的特征 ZC:  我的方法&#xff1a;上面的方式 ESP平衡 1、第1课 (1)、单步跟踪&#xff08;原则&#xff1a;向下的跳转>正常F8&#xff0c;向上的跳转>F4跳过(或者用F2…

android 函数式编程_Android开发人员的函数式编程-第1部分

android 函数式编程by Anup Cowkur通过安纳普考库(Anup Cowkur) Android开发人员的函数式编程-第1部分 (Functional Programming for Android Developers — Part 1) Lately, I’ve been spending a lot of time learning Elixir, an awesome functional programming language…

java编程 内存_Java编程技术之浅析JVM内存

JVMJVM->Java Virtual Machine:Java虚拟机,是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。基本认知&#xff1a;1.JVM是用于运行Java代码的假象计算机&#xff0c;主要有一套字节码指令…

bzoj1116: [POI2008]CLO

传送门&#xff1a;http://www.lydsy.com/JudgeOnline/problem.php?id1116 题目大意&#xff1a;Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 你要把其中一些road变成单向边使得&#xff1a;每个town都有且只有一个入度 题解&am…

java排序算法大全_各种排序算法的分析及java实现

排序一直以来都是让我很头疼的事&#xff0c;以前上《数据结构》打酱油去了&#xff0c;整个学期下来才勉强能写出个冒泡排序。由于要找工作了&#xff0c;也知道排序算法的重要性(据说是面试必问的知识点)&#xff0c;所以又花了点时间重新研究了一下。排序大的分类可以分为两…