JAVA学习八:集合

0.类集概述
类集设置的目的(重点)

对象数组有哪些问题?普通的对象数组的最大问题在于数组中的元素是固定的,不能动态的扩容大小,所以最早的时候可以通过链表实现一个动态对象数组。但是这样做太复杂了,所以在Java中为了方便用户操作各个数据结构,所以引入了类集的概念,有时候就可以把类集称为java对数据结构成熟的实现。

在整个类集中的,这个概念是从JDK1.2后才正式引入的,最早也提供了很多的操作类,但是并没有完整的体术类集的完整概念。

类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口。
所有类集操作的接口或类都在java.util包中。

1.链表
链表[Linked List]是由一组不必相连(指在内存上不必按顺序创建,可以连续也可以不连续)的内存结构(节点),按特定的顺序链接在一起的抽象数据类型。

补充:
抽象数据结构:表示数学中抽象出来的一些操作的集合。
内存结构:内存中的结构,如:struct,特殊内存块…等等之类

数组和链表的区别和优点:

数组是一种连续存储线性结构,元素类型相同,大小相等。

数组的优点:存取速度快

数组的缺点:
事先必须知道数组的长度
插入删除元素很慢
空间通常是有限制的
需要大块连续的内存块
插入删除元素的效率很低

链表是离散存储线性结构
n 个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一 个后续节点,首节点没有前驱节点,尾节点没有后续节点。

链表优点:
空间没有限制
插入删除元素很快

链表缺点:
存取速度很慢

2.二叉树
什么是二叉树

二叉树是树的一种,每个节点最多可具有两个子树,即结点的度最大为 2(结点度:结点拥 有的子树数)。

二叉树就是每个节点不能多于有两个儿子,上面的图就是一颗二叉树,而且还是一种特殊的

二叉树:二叉查找树(binary search tree)。

• 定义:当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。
o 可以看出,这对我们来找一个数是非常方便快捷的。

一棵树至少会有一个节点(根节点)树由节点组成,每个节点的数据结构是这样的:
因此,我们定义树的时候往往是**->定义节点->节点连接起来就成了树**,而节点的定义就是:一个数据、两个指针(如果有节点就指向节点、没有节点就指向null)

二叉树的种类

斜树
所有结点都只有左子树,或者右子树。

满二叉树
所有的分支节点都具有左右节点。

完全二叉树
若设二叉树的深度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

二叉树的一些性质

二叉树第 i 层上的结点数目最多为 2^(i-1) (i≥1)

深度为 h 的二叉树至多有 2^h-1 个结点(h≥1)

包含 n 个结点的二叉树的高度至少为 log2 (n+1)

在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0=n2+1。

Iterator迭代器
Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口
java.util.Iterator 。 Iterator 接口也是Java集合中的一员,但它与 Collection 、 Map 接口有所
不同, Collection 接口与 Map 接口主要用于存储元素,而 Iterator 主要用于迭代访问(即遍历)
Collection 中的元素,因此 Iterator 对象也被称为迭代器。
想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方
法:
public Iterator iterator() : 获取集合对应的迭代器,用来遍历集合中的元素的。下面介绍一下迭代的概念:
迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果
有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取
出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
public E next() :返回迭代的下一个元素。
public boolean hasNext() :如果仍有元素可以迭代,则返回 true。
迭代器的实现原理
我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的
iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,
则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
增强for
增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它
的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

Map集合各子类区别
HashMap: 线程不安全,效率高。不保证存储顺序。
Hashtable: 线程安全,如何实现安全操作,如果第一个线程在调用,那么其他线程会排队执行。效率低。与HashMap实现机制差不多。
ConcurrentHashMap: 采用分段锁机制,保证线程安全。效率又比较高。除了HashMap的机制,它还需要分段排队。
TreeMap: 会按照key来排序。
LinkedHashMap: 在HashMap的基础上保证顺序,当数据存到LinkedHashMap中时同时会存储在一个双向链表中。来实现顺序排列。

散列表散列操作
影响HashMap的实例有两个影响性能的参数:初始容量和负载因子。
初始容量如果不足,会有很多散列操作:把源数据放一边再创建一个两倍大小的哈希表,
把源数据再一个个存进去,重建内部结构。
所以初始容量必须合理,避免浪费性能去做过多的散列操作。
负载因子即散列因子如果无限接近1,那么当桶装到很多,某些桶的链表数据会非常多,这样效率就会很低。
因此散列因子给的越大,越节省空间,查询效率越低,
散列因子给的越小,越浪费空间,查询效率越高。
存储自定义对象

  • HashMap中的key是通过key元素的哈希值来寻找值的

  • 当你的一个自定义对象作为HashMap的键进行存储时,不要轻易改变键的值,

  • 或者不要存在键的位置。
    HashMap<Book,String> data = new HashMap<>();
    Book book1 = new Book(“母猪的产后护理”,“讲述了母猪的产后护理”);
    data.put(book1,“我们人生的第一本书”);
    Book book2 = new Book(“小苹果”,“讲述了苹果的种植”);
    data.put(book2,“我们人生的第二本书”);
    book1.setName(“铜苹果”);
    Book book3 = new Book(“母猪的产后护理”,“讲述了母猪的产后护理”);
    //当把键的对象中的哈希值改变时,如果重新定义一个对象哈希值一样,也无法找到集合中的原数据
    //因为不光要比较哈希值,还要比equals,改变后的对象无法跟新创建的对象equals相等,所以还是找不到数据
    public static void main(String[] args) {
    //ArrayList: 使用的是数组结构,对于增加删除慢,查找块。默认无参构造是创建长度为0的数组。
    //刚开始创建的是一个长度为0的数组,但是第一次存储数据时,长度不够,会扩容+10,变成长度为10的数组;
    ArrayList data = new ArrayList<>();//长度0
    data.add(100);
    data.add(200);
    System.out.println(data.get(0));

      //Vector:   使用的是数组结构,对于增加删除慢,查找块。
      //可以自己在构造方法设置每次扩容增加的数量,ArrayList不可以。
      Vector<Integer> vector = new Vector<>();
      vector.add(123);
      vector.add(234);
      System.out.println(vector.get(1));
    
      //LinkedList:   使用的是双向链表结构,对于增加删除快,查找慢,跟ArrayList形成互补
      //除了add remove get方法还有特殊方法
      //比如向链表的首部添加数据的addFirst,返回首部数据的getFirst,删除首部元素的remove等等
      LinkedList<Integer> linkedList = new LinkedList<>();
    
      //从首部存,从尾部取,就是单段队列
      //linkedList.addFirst(100);
      //linkedList.addFirst(200);
      //Integer i = linkedList.removeFirst();//取出并删除首部数据
      //System.out.println(i);
    
      //当需要使用栈的结构添加数据时使用以下方法
      //压栈
      linkedList.push(100);
      linkedList.push(200);
      //弹栈
      Integer i = linkedList.pop();
      System.out.println(i);
    

    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值