初识Java集合及包装类和泛型的基本使用

Posted 爱敲代码的三毛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识Java集合及包装类和泛型的基本使用相关的知识,希望对你有一定的参考价值。


一、介绍

1.java集合框架是什么?

Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。
其主要表现为将多个元素 element 置于一个单元中,用于对这些元素进行快速、便捷的存储 store 、检索retrieve 、管理 manipulate ,即平时我们俗称的增删查改 CRUD 。
例如,一副扑克牌(一组牌的集合)、一个邮箱(一组邮件的集合)、一个通讯录(一组姓名和电话的映射关系)等等

2.学习java集合的意义

  • 使用成熟的集合框架,有助于我们便捷、快速的写出高效、稳定的代码
  • 学习背后的数据结构知识,有助于我们理解各个集合的优缺点及使用场景

3.java集合关系图

下面这张图将伴随这我们学习Java集合以及数据结构


简单来了解一下:

Collection :用来存储管理一组对象 objects ,这些对象一般被成为元素 elements

  1. Set : 元素不能重复,背后隐含着查找/搜索的语义
    1.1. SortedSet : 一组有序的不能重复的元素
  2. List : 线性结构
  3. Queue : 队列
  4. Deque : 双端队列

Map : 键值对 Key-Value-Pair ,背后隐含着查找/搜索的语义

  1. SortedMap : 一组有序的键值对

二、接口使用实例

1.Collection 接口说明

Collection 官方文档

2.Collection 示例

Collection可以说是所以集合的祖先,只要它底下的接口和类都可以使用这些方法

public static void main(String[] args) {
        //顺序表
        Collection<String> list1 = new ArrayList<>();
        //添加元素
        list1.add("好");
        list1.add("好");
        list1.add("学");
        list1.add("习");
        list1.add("");
        //判断集合是否为空
        System.out.println(list1.isEmpty());
        //删除元素
        list1.remove("!");
        //得到集合中元素的个数
        System.out.println(list1.size());
        //放回一个装有所以集合中元素的数组
        Object[] str = list1.toArray();
        for (Object s : str) {
            System.out.println(s);
        }
        //删除集合中所有元素
        list1.clear();
        System.out.println(list1.isEmpty());
    }

一般我们是不会这么写代码的,这里只是演示一下这个接口。

3.Map 接口说明

HashMap简单来说就是一个Key对应一个值,Key是唯一的。
Map官方文档

4. Map实例

public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
        map.put("三国演义","罗贯中");
        map.put("西游记","吴承恩");
        map.put("水浒传","施耐庵");
        map.put("红楼梦","曹雪芹");

        System.out.println(map.get("西游记"));

        System.out.println(map.containsKey("红楼梦"));
        System.out.println(map.containsValue("李白"));
        Set<Map.Entry<String,String>> entries = map.entrySet();
        for (Map.Entry<String,String> m: entries) {
            System.out.println(m.getKey()+"--->"+m.getValue());
        }
    }

三、泛型

1.泛型的分类

  1. 泛型类
  2. 泛型方法

这里只是先简单认识一下泛型后面会有一篇博客详细讲到。

2.泛型的定义

// 1. 尖括号 <> 是泛型的标志
// 2. E 是类型变量(Type Variable),变量名一般要大写
// 3. E 在定义时是形参,代表的意思是 MyArrayList 最终传入的类型,但现在还不知道
public class MyArrayList<E> {
private E[] array;
private int size;
...
}

注意: 泛型类可以一次有多个类型变量,用逗号分割。

3.泛型背后作用时期和背后的简单原理

  1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念。
  2. 泛型代码在运行期间,就是我们上面提到的,利用 Object 达到的效果(这里不是很准确,以后会做说明)。

4.泛型的使用

// 定义了一个元素是 Book 引用的 MyArrayList
MyArrayList<Book> books = new MyArrayList<Book>();
books.add(new Book());
// 会产生编译错误,Person 类型无法转换为 Book 类型
books.add(new Person());
// 不需要做类型转换
Book book = book.get(0);
// 不需要做类型转换
// 会产生编译错误,Book 类型无法转换为 Person 类型
Person person = book.get(0);

通过以上代码,我们可以看到泛型类的一个使用方式:只需要在所有类型后边跟尖括号,并且尖括号内是真正的类型,即 E 可以看作的最后的类型。

注意: Book 只能想象成 E 的类型,但实际上 E 的类型还是 Object

5.泛型总结

1.泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
3. 泛型是一种编译期间的机制,即 MyArrayList 和 MyArrayList 在运行期间是一个类型。
4. 泛型是 java 中的一种合法语法,标志就是尖括号 <>

注意:泛型的参数不能是简单类型,也就是基本数据类型

四、包装类

Object 引用可以指向任意类型的对象,但有例外出现了,8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?
实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去。

1.基本数据类型和包装类直接的对应关系

除了 Integer 和 Character,基本就是类型的首字母大写。

2.包装类的使用,装箱(boxing)和拆箱(unboxing)

装箱和拆箱有的书上也叫做装包和拆包

    public static void main(String[] args) {
        int i = 10;
// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
        Integer ii = Integer.valueOf(i);
        Integer ij = new Integer(i);
// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
        int j = ii.intValue();
    }

3.自动装箱(autoboxing)和自动拆箱(autounboxing)

可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

		int a = 10;
        Integer b = a;//自动装箱
        int c = b;//自动拆箱

注意:自动装箱和自动拆箱是工作在编译期间的一种机制
我们通过 javap -c 来查看反汇编代码,可以看到在编译期间就发生了拆装箱

五、关于Integer的面试题

来看一段代码

public static void main(String[] args) {
        Integer a1 = 100;
        Integer a2 = 100;
        System.out.println(a1==a2);
        Integer b1 = 200;
        Integer b2 = 200;
        System.out.println(b1==b2);
    }

运行结果


真让人琢磨不透呢,这是怎么一回事呢?这里发生了自动装箱那就得从装箱找原因。来看一下 Integer.valueOf 的源码。



我们知道引用类型比较的是地址,而通过源码我们发现如果Integer 的范围在
-128~127之间就会存在对应的数组上。如果不在范围内就会 new 一个新的Interger 那么必然不会相等。

总结

1.Map里的Key是唯一的
2.泛型和装拆包都是属于编译期间的

完!

JAVA数据结构开始持续更新!

以上是关于初识Java集合及包装类和泛型的基本使用的主要内容,如果未能解决你的问题,请参考以下文章

泛型通配符

详解Java泛型

泛型的泛型的好处

Java8基础知识泛型的约束与局限性

JAVA中,关于可变参数和泛型的问题。

泛型(java菜鸟的课堂笔记)