在Java中,如何以整数的反向二进制形式获取1的位置?
我有一个遗留应用程序,它接受一个整数,将其转换为二进制字符串,反转该字符串,然后获取位(1)的位置作为整数列表。例如:在Java中,如何以整数的反向二进制形式获取1的位置?,java,binary,bit-manipulation,Java,Binary,Bit Manipulation,我有一个遗留应用程序,它接受一个整数,将其转换为二进制字符串,反转该字符串,然后获取位(1)的位置作为整数列表。例如: 6 -> "110" -> "011" -> (2,3) 7 -> "111" -> "111" -> (1,2,3) 8 -> "1000" -> "0001" -> (4) 在现代Java中,没有字符串操作,用什么简洁明了的方法来实现这一点?字符串之间的转换对我来说似乎是浪费,而且我知道没有简单的方法可以翻转字符串(
6 -> "110" -> "011" -> (2,3)
7 -> "111" -> "111" -> (1,2,3)
8 -> "1000" -> "0001" -> (4)
在现代Java中,没有字符串操作,用什么简洁明了的方法来实现这一点?字符串之间的转换对我来说似乎是浪费,而且我知道没有简单的方法可以翻转字符串(no
String.reverse()
)。你可以只计算指数
String str = Integer.toBinaryString(num);
int len = str.length();
List<Integer> list = new ArrayList<>();
for (int i=0; i < len; i ++) {
if (str.charAt(i) == '1') list.add(len - 1 - i);
}
String str=Integer.toBinaryString(num);
int len=str.length();
列表=新的ArrayList();
对于(int i=0;i
您只需测试位,而无需将整数转换为字符串:
列出一个位置(int输入){
List onePositions=new ArrayList();
用于(int位=0;位<32;位++){
如果(输入)&(1只需依次检查位:
List<Integer> bits(int num) {
List<Integer> setBits = new ArrayList<>();
for (int i = 1; num != 0; ++i, num >>>= 1) {
if ((num & 1) != 0) setBits.add(i);
}
return setBits;
}
只需使用String类的indexOf
函数
public class TestPosition {
public static void main(String[] args) {
String word = "110"; // your string
String guess = "1"; // since we are looking for 1
int totalLength = word.length();
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(totalLength - index);
index = word.indexOf(guess, index + 1);
}
}
}
您可以使用此解决方案:
static List<Integer> convert(int input) {
List<Integer> list = new ArrayList<>();
int counter = 1;
int num = (input >= 0) ? input : Integer.MAX_VALUE + input + 1;
while (num > 0) {
if (num % 2 != 0) {
list.add(counter);
}
++counter;
num /= 2;
}
return list;
}
我当然更喜欢安迪自己的答案,即使一开始它看起来很神秘。但是因为这里还没有人有关于streams的答案(即使它们在这里完全不合适):
公共列表getList(intx){
String str=Integer.toBinaryString(x);
最终字符串反转=新的StringBuilder(str).reverse().toString();
返回IntStream.range(1,str.length()+1)
.filter(i->reversed.charAt(i-1)='1')
.boxed()
.collect(Collectors.toList());
}
既然您编写了“现代Java”,这就是如何使用流来实现它的方法(Java 8或更好):
印刷品
[1, 2, 3]
一个愚蠢的回答,只是为了多样化:
BitSet bs = BitSet.valueOf(new long[] {0xFFFFFFFFL & input});
List<Integer> setBits = new ArrayList<>();
for (int next = -1; (next = bs.nextSetBit(next + 1)) != -1;) {
setBits.add(next + 1);
}
bitsetbs=BitSet.valueOf(新长[]{0xffffffffffl&input});
List setbit=new ArrayList();
对于(int next=-1;(next=bs.nextSetBit(next+1))!=-1;){
setbit.add(下一步+1);
}
(感谢pero_hero指出WJS的回答中需要遮罩)只是为了好玩:
Pattern one = Pattern.compile("1");
List<Integer> collect = one.matcher(
new StringBuilder(Integer.toBinaryString(value)).reverse())
.results()
.map(m -> m.start() + 1)
.collect(Collectors.toList());
System.out.println(collect);
patterone=Pattern.compile(“1”);
List collect=one.matcher(
新的StringBuilder(Integer.toBinaryString(value)).reverse()
.结果()
.map(m->m.start()+1)
.collect(Collectors.toList());
系统输出打印项次(收集);
给定原始整数,返回一个包含位位置的列表
static List<Integer> bitPositions(int v) {
return BitSet.valueOf(new long[]{v&0xFF_FF_FF_FFL})
.stream()
.mapToObj(b->b+1)
.collect(Collectors.toList());
}
静态列表位位置(int v){
返回BitSet.valueOf(新长[]{v&0xFF\u FF\u FFL})
.stream()
.mapToObj(b->b+1)
.collect(Collectors.toList());
}
或者如果你想做位移位
static List<Integer> bitPositions(int v ) {
List<Integer> bits = new ArrayList<>();
int pos = 1;
while (v != 0) {
if ((v & 1) == 1) {
bits.add(pos);
}
pos++;
v >>>= 1;
}
return bits;
}
静态列表位位置(int v){
列表位=新的ArrayList();
int pos=1;
而(v!=0){
如果((v&1)==1){
位添加(pos);
}
pos++;
v>>=1;
}
返回位;
}
或者如果需要:
String strValue = Integer.toBinaryString(value);
List<Integer> collect2 = strValue.codePoints()
.collect(ArrayList<Integer>::new,
(l, v) -> l.add(v == '1' ? strValue.length() - l.size() : -1),
(l1, l2) -> l1.addAll(l2)).stream()
.filter(e -> e >= 0)
.sorted()
.collect(toList());
String strValue=Integer.toBinaryString(值);
List collect2=strValue.codePoints()
.collect(数组列表::新建,
(l,v)->l.add(v=='1'?strValue.length()-l.size():-1),
(l1,l2)->l1.addAll(l2)).stream()
.过滤器(e->e>=0)
.已排序()
.collect(toList());
我可以提出一个纯粹的位解决方案吗
static List<Integer> onesPositions(int input)
{
List<Integer> result = new ArrayList<Integer>(Integer.bitCount(input));
while (input != 0)
{
int one = Integer.lowestOneBit(input);
input = input - one;
result.add(Integer.numberOfTrailingZeros(one));
}
return result;
}
静态列表一个位置(int输入)
{
列表结果=新的ArrayList(整数.位计数(输入));
while(输入!=0)
{
int one=整数。低位(输入);
输入=输入-一;
结果.add(整数.numberoftrailingzero(一));
}
返回结果;
}
该解决方案在算法上是最优的:
单个内存分配,使用Integer.bitCount
预先适当调整ArrayList
的大小
循环迭代的最小次数,每组1位
内部循环相当简单:
Integer.lowstonebit
仅返回输入集最低位的int
输入-一个
从输入中“取消设置”该位,用于下一次迭代
Integer.numberoftrailingzero
以二进制形式计算尾随零的数量,有效地为我们提供最低1位的索引
1值得注意的是,这可能不是编译后的最佳方式,相反,基于位计数的显式0..n
循环更容易在JIT中展开。流版本的@Matthieu M。答案:
List<Integer> list = IntStream.iterate(value, (v) -> v != 0, (v) -> v & (v - 1))
.mapToObj(val -> Integer.numberOfTrailingZeros(val) + 1)
.collect(toList());
List List=IntStream.iterate(值,(v)->v!=0,(v)->v&(v-1))
.mapToObj(val->Integer.numberOfTrailingZeros(val)+1)
.collect(toList());
不过,您不需要转换为字符串。@Andy Turner true,我只是不知道如何使用位移位。我认真地问自己:为什么?所有的解决方案都会以某种方式检查是否有位,然后以某种方式存储索引。也许不需要字符串转换,但按照今天的标准,我怀疑它是否对索引有多大影响性能。注意:新的StringBuilder.reverse().toString()
可用于反转字符串。在这里使用字符串@maio290在概念上是不可靠的。性能与此无关(尽管这是一个结果,如果这是一个频繁的操作,性能实际上可能会变得相关)。这有什么用?我想不出它的实际用途。@inetphantom,如我所说,legacy system。这实际上是数据库中一个非常特殊的“外键”。整数对一组ID编号进行编码,以便在数据库表中查找。看起来不错。我从不使用这些二进制/位操作,因此我永远记不住它们。显然:-)用字符串做这件事太糟糕了。这个问题有很多很好的答案!我认为这个问题中的迭代,用shift-right操作符,非常聪明。而且
static List<Integer> bitPositions(int v) {
return BitSet.valueOf(new long[]{v&0xFF_FF_FF_FFL})
.stream()
.mapToObj(b->b+1)
.collect(Collectors.toList());
}
static List<Integer> bitPositions(int v ) {
List<Integer> bits = new ArrayList<>();
int pos = 1;
while (v != 0) {
if ((v & 1) == 1) {
bits.add(pos);
}
pos++;
v >>>= 1;
}
return bits;
}
String strValue = Integer.toBinaryString(value);
List<Integer> collect2 = strValue.codePoints()
.collect(ArrayList<Integer>::new,
(l, v) -> l.add(v == '1' ? strValue.length() - l.size() : -1),
(l1, l2) -> l1.addAll(l2)).stream()
.filter(e -> e >= 0)
.sorted()
.collect(toList());
static List<Integer> onesPositions(int input)
{
List<Integer> result = new ArrayList<Integer>(Integer.bitCount(input));
while (input != 0)
{
int one = Integer.lowestOneBit(input);
input = input - one;
result.add(Integer.numberOfTrailingZeros(one));
}
return result;
}
List<Integer> list = IntStream.iterate(value, (v) -> v != 0, (v) -> v & (v - 1))
.mapToObj(val -> Integer.numberOfTrailingZeros(val) + 1)
.collect(toList());