Collection、泛型的学习

Collection、泛型

1,、Collection概念

  • Collection集合:集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组区别:

数组:长度固定 .................集合:长度可变

数组:同一类型的元素 .......集合:存储的都是对象。而且对象的类型可以不一致

Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,子接口分别是java.util.Listjava.util.Set

List的特点是元素有序、元素可重复、有索引可用for循环

Set的特点是元素无序,存取无序,不允许元素重复,没索引(不能用普通for循环)。

2、单列集合的体系结构

List集合:

ArrayList:底层是数组实现的,查询快,增删慢

LinkedList:底层是链表式的,查询慢,增删快

Set集合:

HashSet:底层是哈希表+(红黑树)实现的,无索引、不可以存储重复元素、存取无序

LinkedHashSet:底层是哈希表+链表实现的,无索引,不可以存储重复元素,可以保证存取顺序。

TreeSet:底层是二叉树实现,一般用于排序。

3 Collection 常用功能

集合(List和Set)常用的一些方法:

  • boolean add(E e): 向集合中添加元素 。
  • void clear() :清空集合中所有的元素。
  • boolean remove(E e): 把给定的对象在当前集合中删除。
  • boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • boolean isEmpty(): 判断当前集合是否为空。
  • int size(): 返回集合中元素的个数。
  • Object[] toArray(): 把集合中的元素,存储到数组中。

创建集合对象,可以使用多态:Collection coll = new ArrayList<>();

3、Iterator迭代器

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。对集合进行遍历

Iterator接口的常用方法

  • public <E> next():返回迭代的下一个元素。
  • public boolean hasNext():判断,如果仍有元素可以迭代,则返回 true。

Iterator迭代器是一个借口,无法直接使用,需要借助实现类对象

迭代器使用步骤(重点):

1、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)

2、使用Iterator接口中的方法hasNext()判断还有没有下一个元素

3、使用Iterator接口中的方法next()取出集合中的下一个元素

示例:Collection<String> coll = new ArrayList<> [];

注意:Iterator接口也是泛型的,迭代器的泛型跟着集合走,迭代就是什么泛型迭代器取出集合中的元素代码,是一个重复的过程,可以循环优化。

不知道元素数量,可以使用while循环:

while (coll.hasNext()){
String e = coll.next();
System.out.printlln(e);
}

迭代器&增强for:

迭代器

1.通过集合对象取代迭代器对象

2.使用循环遍历迭代器

3.判断迭代器对象中是都还有元素

4.有元素则获取

增强for循环:底层使用的也是迭代器,简化了迭代器的书写。

for(数据类型 变量: 容器对象 (Collection集合or数组)){

循环体语句

}

注意事项:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。

例:

int[ ] arry = {1,2,3,4,5}
//使用增强for循环遍历数组
for(int i:arr){
Symstem.out.prinln(i);
}

迭代器的实现原理

coll.iterator();获取迭代器的实现类对象,并把指针指向集合的-1索引

while (coll.hasNext()) 判断集合中还有没有下一个元素

String e = coll.next(); 1.取出下一个元素 2.把指针向后移动一位

2.泛型

泛型:是一种未知的数据类型,当我们不知道使用数据类型的时候可以使用泛型。

泛型也可以看成是一个变量,用来接收数据类型 E e:Element T t:Type

使用泛型的好处

创建集合对象,不适用泛型

好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据。

弊端:不安全,会引发异常。

创建集合对象,使用泛型

好处

  • 避免了类型强转的麻烦。
  • 将运行时期的运行异常ClassCastException,转移到了编译时期变成了编译失败。

弊端:

泛型是什么类型,只能存储什么类型的数据。

泛型的定义和使用

创建对象的时候确定泛型的类型

修饰符 class 类名<代表泛型的变量> { }

含有泛型的方法

定义格式:

修饰符<泛型>返回值类型 方法名(参数列表(使用泛型)){

方法体

}

例:

public <M> void method02(M m){
方法体
}

含有泛型的接口

定义格式:

修饰符 interface接口名<代表泛型的变量> {  }

public interface MyGenericInterface<E>{
public abstract void add(E e);
    public abstract E getE();  }

两种使用方法:

1、定义类时确定泛型的类型

2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型

4、泛型通配符(?)

4.1 概念

泛型通配符(?):代表任意的数据类型

使用方法:不能创建对象使用,只能作为方法使用。

注意:泛型是没有继承概念的。

泛型的上限限定:?extens E代表使用的泛型只能是E类型的子类/本身

泛型的下限限定:?super E代表使用的泛型只能是E类型的父类/本身

4.2 斗地主案例

1,准备牌:

54张牌,存储到一个集合中

特殊性:大王小王 其他52张牌:♠ ♥ ♦ ❀

定义一个数组/集合,存储4种花色

定义一个数组/集合,存储13个序号

循环遍历两个数组/集合:组装52张牌

2,洗牌

使用集合工具类Collection方法

static void shuffle(List<?> list)使用指定的随机源对指定列表进行置换。

会随机打乱集合的顺序

3、发牌

要求:1人17张牌,剩余3张伟底牌,一人一张轮流发票:集合的索引(0-53)%3

4,看牌

直接打印集合,遍历存储玩家和底牌的集合

练习代码

public class DouDiZHU {
public static void main(String[] args) {
//准备牌  准备54张牌 ArrayList集合,String泛型
ArrayList<String> poker = new ArrayList<>();
//连个数组 一个花色一个序号
String[] colors = {"♠", "♥", "♦", "❀"};
String[] numbers = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
poker.add("大王");
poker.add("小王");
//2.组装扑克 循环嵌套遍历两个数组,组装52张牌
for (String number : numbers)
for (String color : colors) {
//System.out.println(color+number);
poker.add(color + number);

}
System.out.println(poker);
//3,洗牌,使用shuffle方法
Collections.shuffle(poker);
System.out.println(poker);
//发牌  定义4集合,存储玩家的牌和底牌
ArrayList<String> p1 = new ArrayList<>();
ArrayList<String> p2 = new ArrayList<>();
ArrayList<String> p3 = new ArrayList<>();
ArrayList<String> p4 = new ArrayList<>();
//遍历poker集合,获取每一张牌,轮流发牌
//剩余3张给底牌
//要先留底牌不然牌发完了
for (int i = 0; i < poker.size(); i++) {
//获取牌
String p = poker.get(i);
if (i >= 51) {
p4.add(p);
} else if (i % 3 == 0) {
p1.add(p);
} else if (i % 3 == 2) {
p2.add(p);
} else if (i % 3 == 1) ;
p3.add(p);
}
System.out.println("玩家1:"+p1);
System.out.println("玩家1:"+p2);
System.out.println("玩家1:"+p3);
System.out.println("底牌:"+p4);
}
}

5.常见数据结构

数据结构:数据存储的常用结构有:栈、队列、数组、链表和红黑树

栈:先进后出(像弹匣) :

栈的入口、出口的都是栈的顶端位置。

队列

先进先出: 队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口。

数组:

查询快:数组的地址是连续的,通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素。

增删慢:数组的长度是固定的,我们想要增加/删除一个元素,必须创建一个新数组,把数组的数据复制过来。

在堆内存中,频繁地创建数组、复制数组中的元素,销毁数组,效率低下。

链表

查询慢:链表中地址不是连续的,每次查询元素都要从头开始

增删快:链表结构,增加/删除一个元素,对链表的整体结构没有影响,所以增删快。

单向链表:链表中只有一条链子,不能保证元素的顺序(存储和取出的顺序可能不一致)

双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合

红黑树

二叉树:binary tree ,是每个结点不超过2的有序树(tree) 。 每个结点上都最多只能有两个子结点。

排序树/查找树:在二叉树基础上,元素是有大小顺序的,左子树小,右子树大

平衡树:左孩子和右孩子是相等的

不平衡树:左孩子不等于右孩子

红黑树:趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数和最小次数不能超过2倍。

红黑树的约束:

  1. 节点可以是红色的或者黑色的
  2. 根节点是黑色的
  3. 叶子节点(特指空节点)是黑色的
  4. 每个红色节点的子节点都是黑色的
  5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值