Java小记5(第五周)

关于map和hashmap的知识

现实生活中,我们经常需要成对存储某些信息。比如,我们使用的微信,一个手机号只能对应一个微信账户。这就是一种成对存储的关系。

      Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。

      Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。

表9-3 Map接口中常用的方法

 HashMap采用哈希算法实现,是Map接口最常用的实现类。 由于底层采用了哈希表存储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap在查找、删除、修改方面都有非常高的效率。

【示例9-7】Map接口中的常用方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public class TestMap {

    public static void main(String[] args) {

        Map<Integer, String> m1 = new HashMap<Integer, String>();

        Map<Integer, String> m2 = new HashMap<Integer, String>();

        m1.put(1"one");

        m1.put(2"two");

        m1.put(3"three");

        m2.put(1"");

        m2.put(2"");

        System.out.println(m1.size());

        System.out.println(m1.containsKey(1));

        System.out.println(m2.containsValue("two"));

        m1.put(3"third"); //键重复了,则会替换旧的键值对

        Map<Integer, String> m3 = new HashMap<Integer, String>();

        m3.putAll(m1);

        m3.putAll(m2);

        System.out.println("m1:" + m1);

        System.out.println("m2:" + m2);

        System.out.println("m3:" + m3);

    }

}

      执行结果如图9-11所示:

图9-11 示例9-7运行效果图

      HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。

HashMap与HashTable的区别

      1. HashMap: 线程不安全,效率高。允许key或value为null。

      2. HashTable: 线程安全,效率低。不允许key或value为null。

 HashMap底层实现采用了哈希表,这是一种非常重要的数据结构。对于我们以后理解很多技术都非常有帮助(比如:redis数据库的核心技术和HashMap一样),因此,非常有必要让大家理解。

      数据结构中由数组和链表来实现对数据的存储,他们各有特点。

      (1) 数组:占用空间连续。 寻址容易,查询速度快。但是,增加和删除效率非常低。

      (2) 链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。

▪ 扩容问题

      HashMap的位桶数组,初始大小为16。实际使用时,显然大小是可变的。如果位桶数组中的元素达到(0.75*数组 length), 就重新调整数组大小变为原来2倍大小。

      扩容很耗时。扩容的本质是定义新的更大的数组,并将旧数组内容挨个拷贝到新数组中。

 JDK8将链表在大于8情况下变为红黑二叉树

      JDK8中,HashMap在存储一个元素时,当对应链表长度大于8时,链表就转换为红黑树,这样又大大提高了查找的效率。

      下一节,我们简单介绍一个二叉树。同时,也便于大家理解TreeMap的底层结构。

Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.javaJava类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值