持有对象学习笔记

持有对象

前言

如果一个程序只包含固定数量的且生命周期都是已知的对象,那么这是一个非常简单的程序。

但是业务中,程序总是根据运行时才知道的某些条件去创建新对象

if(condition) {
    A a = new A();
}

在此之前,不知道需要创建什么类型的多少对象。所以,就不能依靠创建命名的引用来持有一个对象。

相信都知道数组,数组可以保存一组基本数据类型数据(byte short int long char boolean float double),数组是最高效的对象持有方式。但是数组有它的局限性,比如不可扩展性(数组尺寸固定)。

Java有一套完整的容器类来解决这个问题(java.util)。其中基本类型为List、Set、Queue、Map。这些类也成为集合类

基本概念

Java容器类的作用是储存对象,将其分为两个不同的概念:

Collection(集合)

一个独立元素的序列,这些元素都服从一条或多条规则。 List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照排队规则来确定对象的顺序。

Map(映射)

一组成对的“键值对”对象,允许你使用键来查找值(ArrayList可以通过数字来查找值,在某种意义上讲,它将数字和对象关联在一起)。映射表允许我们用另一个对象来查找某个对象,这是一个很强大的功能,所以map也被称为“关联数组”、“字典”。

如何创建一个基本的List

// 但你只需要用到List接口规范的公用方法时,你可以直接向上转型
// 这样获得的list将没有ArrayList额外的功能
// 参数表示的是设置起始存储空间,缺省参数则默认为10
List<Object> objectList = new ArrayList<>(10);

注意:在实例化ArrayList类时,应根据业务需求合理初始化initialCapacity,这是一个良好的习惯,这样获对象的速度将会有提升,至于原理,请看JDK源码,源码中看到,如果容量超出Capacity,会调用Arrays.copyOf(),这就等于每次超出都会开辟新的内存空间新建一个数组

添加一组元素

在Java.utl包中,Arrays跟Collections类中有很多实用方法,可以在一个Collection中添加一组元素。

ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4));
Integer[] array = {5,6,7};
list.addAll(Arrays.asList(array));
System.out.println(list.size());// 将会输出7 
Collections.addAll(list, 1,2,3,5);
System.out.println(list.size());// 将会输出11

注意:你可以通过Arrays.asList()方法直接生成一个List,但是这个list底层是数组,所以使用add()或delete()时可能会引发改变数组尺寸的尝试,因此运行时,可能获取“Unsupported Operation”错误。

List

List承诺可以将元素维护在特定的序列中。List接口在Collection的基础上添加了大量的方法声明,其中包含可以在List的中间插入和移除元素。

有两种类型的List

ArrayList

ArrayList擅长随机访问元素,但是在List的中间插入和移除元素时较慢。

LinkedList

LinkedList在随机访问方面相对较慢,但它的特性集较ArrayList更大。

        LinkedList<Integer> linkedList = new LinkedList<>(Arrays.asList());

        // addLast()、add()将某元素插入到列表的尾部,addFirst()将元素插入到列表的头部
        linkedList.addLast(3);
        linkedList.addFirst(1);
        linkedList.add(2);

        // getFirst()和element()、peek()都是返回列表的第一个元素
        // 区别在于当集合为空时,peek()返回null,而其他抛出NoSuchElementException
        System.out.println(linkedList.getFirst());
        System.out.println(linkedList.element());
        System.out.println(linkedList.peek());

        // removeFirst()和remove()、poll()都是返回并移除列表的第一个元素
        // 区别在于当集合为空时,poll()返回null,而其他抛出NoSuchElementException
        System.out.println(linkedList.removeFirst());
        System.out.println(linkedList.remove());
        System.out.println(linkedList.poll());

        // 返回并移除列表的最后一个元素
        System.out.println(linkedList.removeLast());

栈Stack

栈通常指的是LIFO(Last In, First Out)的容器,有时栈也被称为叠加栈。 LinkedList能直接被作为Stack使用。

Set

Set不保存重复的元素。Set中最常用被使用的是测试归类属性,你可以很容易地询问到某个对象是否在某个Set。 正因如此,查找成为Set最重要的操作。 所以我们通常使用HashSet来实现set,因为它专门对快速查找进行了优化。

Set具有与Collection完全一样的接口。实际上Set就是Collection,只是行为不同。(表现不同的行为)

Map

将对象映射到其他对象的能力是一种解决问题的杀手锏

Queue

队列是一个典型的FIFO(先进先出)容器。队列咋并发编程中特别重要。 由于LinkedList扩展至Queue接口,所以LinkedList可以向上转型为Queue。 注意:PriorityQueue是一个特别的队列,因为他不是常规的FIFO容器,元素会以自然排序排列,也就是说,最小的值具有最高的优先级。

PriorityQueue<Integer> queue = new PriorityQueue<>();
// offer方法跟add方法一样,都是在容器尾部添加元素
// 查看add的源码会发现调用了offer方法
queue.offer(2);
queue.add(1);
// peek是在不移除元素的情况下返回容器第一个元素
// 当容器为空时返回null,而调用element会抛出异常
System.out.println(queue.peek()); // 将返回1
// poll将会移除并返回头元素
// 当容器为空时返回null,而调用remove会抛出异常
System.out.println(queue.poll()); // 将返回1

迭代器Iterator

迭代器是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序人员不需要关心所需迭代的序列的结构。此外,迭代器通常被称为轻量级对象:创建它的代价很小。使用迭代器的流程如下:

  • 使用方法iterator()方法返回一个Iterator对象。Iterator将返回序列的第一个元素
  • 使用next()获得序列中的下一个对象
  • 使用hasNext()检查是否还有元素
  • 使用remove()将新近返回的元素删除
Iterator<Integer> iterator = collection.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());            iterator.remove();
}

注意:当你在代码中使用foreach语法时,其实是使用了iterator

Test.java
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,4,5,6));
for (Integer e : list) {
    System.out.println(e);
}
// 这是反编译后的class文件
Test.class
ArrayList<Integer> list = new ArrayList(Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6)}));
Iterator var4 = list.iterator();

while(var4.hasNext()) {
    Integer e = (Integer)var4.next();
    System.out.println(e);
}

转载于:https://my.oschina.net/StupidZhe/blog/1557942

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值