今天在使用java写代码的时候,用byte数组作为map的key来使用,发现在遍历的时候get到之前传进去的值总是为空,很是困惑,后来查了下资料发现java中的字节数组不能直接作为map的key来使用.

/**

* 找到当前区块链中所有UTXO

*/

public List findAllUtxos(String sendAddress) {

//遍历所有的区块,找出交易发起人能够解锁的所有没有花费的交易输出

List utxoInfos = new ArrayList<>();

Iterator blockIterator = new Iterator(tailHash);

//byte[]不能直接作为map的key使用,所以需要将txid转换成string才能使用

Map> spentOutputs = new HashMap<>();

for (; ; ) {

Block block = blockIterator.getBlock();

for (Transaction tx : block.transactions) {

System.out.println("tag2:outputs length is " + tx.outputs.length + " tx id is " + new BigInteger(tx.id).toString(16));

ScanTransaction:

//遍历所有的交易输出

for (int i = 0; i < tx.outputs.length; i++) {

//如果发现该交易已经有被引用的交易输出,就开始判断

List idList = spentOutputs.get(new String(tx.id));

if (idList != null) {

System.out.println(idList.toString());

for (Integer index : idList) {

if (i == index) {

System.out.println("find spent output,continue scan next input");

continue ScanTransaction;

}

}

}

//如果交易发起人能使用,将其添加进去

TxOutput output = tx.outputs[i];

if (output.canUnlockUTXOWith(sendAddress)) {

UtxoInfo utxoInfo = new UtxoInfo();

utxoInfo.id = tx.id;

utxoInfo.index = i;

utxoInfo.output = output;

utxoInfos.add(utxoInfo);

}

}

//遍历所有的交易输入,找到已经花费掉的,每次循环都创建一个List对象

List spentTxIds = new ArrayList<>();

if (!tx.isCoinBase()) {

for (int i = 0; i < tx.inputs.length; i++) {

TxInput input = tx.inputs[i];

if (input.canUnlockWith(sendAddress)) {

spentTxIds.add(i);

//一定要注意这里的txid是输入中引用的交易id,不是本次循环的txid

System.out.println("find used utxo,tx id is " + new BigInteger(input.txId).toString(16) + "index is " + i);

spentOutputs.put(new String(input.txId), spentTxIds);

}

}

}

}

if (block.prevHash == null || block.prevHash.length == 0) {

break;

}

}

return utxoInfos;

}

原因是这样的,当使用byte[]作为key的时候,map会对这个字节数组的地址进行hashcode得到一个值作为key,而不是以内容作为它的key,所以两次byte数组地址不一样的话,得到的结果就会完全不同.

有三种解决方案:

Wrapping in a String, but then you have to be careful about encoding issues (you need to make certain that the byte -> String -> byte gives you the same bytes).

Use List(can be expensive in memory).

Do your own wrapping class, writing hashCode and equals to use the contents of the byte array.

分别是将byte转成字符串String,我在代码里也是这么改的;第二是使用List代替;第三是实现你自己的包装类,重写hashcode和equals方法来达到以内容作为key的目的.

再来类比一下go语言中的map,map的key需要能够进行比较的数据类型.那些内置复杂类型如slice,function和map以及包含这些类型字段的结构体也是不能用来做map的key的.

参考资料:

--EOF--

发表于 2018-12-01 15:25:00

,并被添加「java、go」标签。

本站使用「署名 4.0 国际」创作共享协议,转载请注明作者及原网址。更多说明 »

提醒:本文最后更新于 830 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「java相关」的其它文章 »

java map byte[],java中byte数组不能作为map的key使用相关推荐

  1. java sbyte_JAVA与c#中byte取值范围的差异

    C#中分有符号类型的sbyte和无符号类型的byte Console.WriteLine("byte.min:{0},byte.max:{1},{2}byte", byte.Min ...

  2. java stream 转 file_java 中 byte[]、File、InputStream 互相转换

    1.将File.FileInputStream 转换为byte数组: File file = new File("test.txt"); InputStream input = n ...

  3. java 数组排序论文_Java中运用数组的四种排序方法

    标签: <1>利用Arrays带有的排序方法快速排序 import java.util.Arrays; 2 public class Test2{ public static void m ...

  4. easypoi list中的map导出_Java中的集合类(List,Set.Map)

    1.List 1.1 Arraylist 与 LinkedList 区别 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全: 底层数据结构: Arr ...

  5. Java中Array、List、Map相互转换

    引言: 在实际项目开发中或者一些算法面试题目中经常需要用到Java中这三种类型的相互转换,比如对于一个整型数组中寻找一个整数与所给的一个整数值相同,正常情况下第一反应会想到用for循环直接遍历这个数组 ...

  6. 关于java中的数组

    前言:最近刚刚看完了<Java编程思想>中关于数组的一章,所有关于Java数组的知识,应该算是了解的差不多了.在此再梳理一遍,以便以后遇到模糊的知识,方便查阅. Java中持有对象的方式, ...

  7. Java解析json字符串和json数组

    Java解析json字符串和json数组 public static Map<String, String> getUploadTransactions(String json){Map& ...

  8. 【Java基础】Java IO编程:输入输出流、内存流、打印流、缓冲流BufferedReader、扫描流Scanner、序列化与反序列化

    文章目录 第11章.Java IO编程 11.1 文件操作类:File 11.2 字节流与字符流 字节输出流:OutputStream OutputStream类 FileOutputStream类 ...

  9. Java中 byte[]数组序列化和fastjson序列化区别

    Java中 byte[]数组序列化和fastjson序列化区别 Java中,对于对象可以通过序列化成byte数组或者序列化成json形式,这里做下两者的对比. 首先看下实现方式: 1 byte数组序列 ...

最新文章

  1. Python装饰器实现一个代码计时器?
  2. python命令提示符窗口在哪里_详解python命令提示符窗口下如何运行python脚本
  3. 微软开源AI诊断工具Error Analysis
  4. react(85)--error:Error creating bean with name ‘onlineStudyController‘:
  5. MFC中树形控件的应用——电话簿
  6. Python操作MySQL的封装类
  7. ISO14229-1道路车辆-统一诊断服务(UDS)-1
  8. 程序员都在用的电脑小技巧,一遍就学会,每天早下班一小时
  9. 图的深度优先遍历及广度优先遍历
  10. 数据分析之描述性统计分析
  11. Java异常处理之异常类继承层次
  12. 【RDMA】qp数量和RDMA性能(节选)|连接数
  13. 在linux上使用spi-lcd屏 ST7735
  14. 乘云而上,易捷行云入选“2020中国企服行业独角兽TOP50”
  15. 模拟城市服务器连接中断 正试着,【模拟城市5】确认DRM在线 中断不会被踢
  16. 备赛脱脂经验分享_敲黑板,备赛这几招如果你还不知道,赶快学起来吧!
  17. 运算放大器的差分放大电路
  18. 到底应不应该【跨专业】考研计算机?希望大么?
  19. Windows10 会不会成为微软的新起点?
  20. 如果哥白尼也玩“虚拟化”和“超融合”

热门文章

  1. c语言可以编写图形界面吗,「分享」C语言如何编写图形界面
  2. linux添加文件后无法启动,linux安装后grub无法启动
  3. php 相册分类,这款不需要网络就可以智能识别分类照片,让你的相册不再混乱...
  4. Java刷漆问题代码_Java实现蓝桥杯历届试题格子刷油漆
  5. linux控制台编辑模式下换行,linux控制台命令的换行识别问题
  6. mysql 阿里云 优化_MySQL性能优化速记
  7. Linux/unix 查看端口占用
  8. C和C++的关键字区别
  9. 【Debug】— C++ 表达式必须包含类类型
  10. android studio你可能忽视的细节——启动白屏?drawable和mipmap出现的意义?这里都有!!!...