资讯专栏INFORMATION COLUMN

【Java数据结构】初识集合框架——List的使用(附加自动发牌案例)

oogh / 3535人阅读


泛型

什么是泛型

泛型:
即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型是在C#2.0引入的。泛型(Genericity)的字面意思是指具有在多种数据类型上皆可操作的含意,与模板有些相似

优点:
泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。泛型通常用与集合以及作用于集合的方法一起使用。

泛型的分类

  1. 泛型类
  2. 泛型方法

泛型的定义简单演示

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

   public class MyArrayList<E> {    private E[] array;    private int size;    ...     }

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

  1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念

  2. 泛型代码在运行期间,就是我们上面提到的,利用 Object 达到的效果(这里不是很准确,后期会专门写一篇博客讲泛型)。

  3. < T > 代表当前类是一个泛型类

  4. new T[10]; 不能new泛型类型的数组 T[] t = new T[];

  5. 泛型的意义
    ①在存储元素的时候,可以自动进行类型检查
    ②在获取元素的时候,可以进行自动类型的转换

  6. 泛型类型的参数:不能是简单类型

  7. 泛型类型的参数,是不参与类型的组成的

面试问题:

  • 泛型到底是怎么编译的?
  • 1、泛型只在编译的时候,起作用。在运行的时候,是没有泛型的概念的!!!
  • 2、擦除机制 -> Object -> 不严谨-> 我们可以给定一个擦除边界

泛型类的使用

// 定义了一个元素是 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。
  • Java中的泛型仅仅是一个编译时的概念,在运行时,所有的泛型信息都被消除了,这被称为泛型擦除。

泛型总结

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

包装类

Object 引用可以指向任意类型的对象,但有例外出现了,8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?

实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去

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

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

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

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

手动装箱 也有 自动装箱拆箱 也一样

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

注意:自动装箱和自动拆箱是工作在编译期间的一种机制

List的使用

List常用方法

方法解释
booleanadd(E e) 尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection c)尾插 c 中的元素
E remove(int index)删除 index 位置元素
boolean remove(Object o)删除遇到的第一个 o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List subList(int fromIndex, int toIndex)截取部分 list

使用示例

import java.util.List;import java.util.ArrayList;import java.util.LinkedList;public class ListDemo {    public static void main(String[] args) {        List<String> courses = new ArrayList<>();        courses.add("Kobe");        courses.add("Jordan");        courses.add("Westbrook");        courses.add("Durant");        // 和数组一样,允许添加重复元素        courses.add("Kobe");        // 按照添加顺序打印        System.out.println(courses);        // 类似数组下标的方式访问        System.out.println(courses.get(0));        //给目标位置设置新元素        courses.set(0, "Jordan");        System.out.println(courses);        // 截取部分 [1, 3) 注意这里是左开右闭区区间        List<String> subCourses = courses.subList(1, 3);        System.out.println(subCourses);        // 重新构造        List<String> courses2 = new ArrayList<>(courses);        System.out.println(courses2);        List<String> courses3 = new LinkedList<>(courses);        System.out.println(courses3);        // 引用的转换        ArrayList<String> courses4 = (ArrayList<String>)courses2;        System.out.println(courses4);        //LinkedList c = (LinkedList)course2; 错误的类型        LinkedList<String> courses5 = (LinkedList<String>)courses3;        System.out.println(courses5);        //ArrayList c = (ArrayList)course3; 错误的类型        }    }

运行结果如下:

自动发牌案例

分为三个java文件

import java.util.ArrayList;import java.util.List;public class TestDemo {    public static void main(String[] args) {        List<Card> deck = CardDemo.buyDeck();        System.out.println("买来的新牌");        System.out.println(deck);        System.out.println("===========================");        CardDemo.shuffle(deck);        System.out.println("洗过后的牌");        System.out.println(deck);        System.out.println("===========================");        //三个人,每个人轮流抓牌,一个人五张牌        List<List<Card>> hands = new ArrayList<>();//二维数组的思维        hands.add(new ArrayList<>());//加一个人        hands.add(new ArrayList<>());//再加一个人        hands.add(new ArrayList<>());//再加一个人,共三个人        for (int i = 0; i < 5 ; i++){            for (int j = 0; j < 3; j++){                hands.get(j).add(deck.remove(0));                //这里的remove返回顺序表里被移除的元素,刚好牌堆里少一张牌            }        }        System.out.println("剩余的牌");        System.out.println(deck);        System.out.println("A手中的牌");        System.out.println(hands.get(0));        System.out.println("B手中的牌");        System.out.println(hands.get(1));        System.out.println("C手中的牌");        System.out.println(hands.get(2));    }}
public class Card {    private int rank;//牌值    private String suit;//花色    public Card(int rank, String suit) {        this.rank = rank;        this.suit = suit;    }    @Override    public String toString() {        return String.format("[%s %d]", suit, rank);    }}
import java.util.ArrayList;import java.util.List;import java.util.Random;public class CardDemo {    private static final String[] suits = {"♥", "♠", "♦", "♣"};    //买一副牌    public static List<Card> buyDeck() {        List<Card> deck = new ArrayList<>(52);        for (int i = 0; i < 4; i++) {            for (int j = 1; j <= 13; j++) {                String suit = suits[i];                int rank = j;                deck.add(new Card(rank, suit));//顺序表默认是尾插            }        }        return deck;    }    public static void swap(List<Card> deck, int i, int j) {        Card temp = deck.get(i);        deck.set(i, deck.get(j));        deck.set(j, temp);    }    public static void shuffle(List<Card> deck){        Random rand = new Random(20211122);        for (int i = deck.size() - 1; i > 0; i--){            int r = rand.nextInt(i);//生成0~i的随机正整数            swap(deck, i ,r);        }    }

?????????????????????????
       ❤原创不易,如有错误,欢迎评论区留言指出,感激不尽❤
       ❤               如果觉得内容不错,给个三连不过分吧~        ❤
       ❤                            看到会回访~                                      ❤
??????????????????????

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/124737.html

相关文章

  • Java编程基础19——Map集合&斗地主案例

    摘要:使用默认随机源对指定列表进行置换。将集合排序使用二分搜索法搜索指定列表,以获得指定对象根据元素的自然顺序,返回给定的最大元素。 1_Map集合概述和特点 A:Map接口概述 查看API可以知道: 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 B:Map接口和Collection接口的不同 Map是双列的,Collection是单列的 Map...

    ygyooo 评论0 收藏0
  • map集合学习

    摘要:提供了专门的集合类用来存放这种对象关系的对象,即接口。中的集合,元素是成对存在的理解为夫妻。中的集合称为单列集合,中的集合称为双列集合。根据指定的键,在集合中获取对应的值。 day04 【Map】 主要内容 Map集合 教学目标 [ ] 能够说出Map集合特点 [ ] 使用Map集合添加方法保存数据 [ ] 使用键找值的方式遍历Map集合 [ ] 使用键值对的方式遍历Map集合 [ ...

    peixn 评论0 收藏0
  • Java集合框架——Map接口

    摘要:第三阶段常见对象的学习集合框架集合在实际需求中,我们常常会遇到这样的问题,在诸多的数据中,通过其编号来寻找某一些信息,从而进行查看或者修改,例如通过学号查询学生信息。面试题和的区别是单列集合的顶层接口,有子接口和。 第三阶段 JAVA常见对象的学习 集合框架——Map集合 showImg(https://segmentfault.com/img/remote/1460000019683...

    princekin 评论0 收藏0
  • 1、Map接口 2、模拟斗地主洗牌发牌

    摘要:中的集合称为单列集合,中的集合称为双列集合。洗牌通过数字完成洗牌发牌发牌将每个人以及底牌设计为将最后张牌直接存放于底牌,剩余牌通过对取模依次发牌。存放的过程中要求数字大小与斗地主规则的大小对应。 01Map集合概述 A:Map集合概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同  a:Collection中的集...

    付伦 评论0 收藏0
  • PHP+Redis实战教程(1):初识Redis

    摘要:本文为实战读书笔记简介是一个非关系型远程内存数据库,由于操作都在内存中,所以的速度非常快,性能十分强劲。同时,还可以自动的以两种不同的方式将数据库内容持久化到硬盘,保证数据的完整性。数据格式支持字符串列表集合散列有序集合数据类型。 本文为《Redis实战》读书笔记 Redis简介 Redis是一个非关系型远程内存数据库,由于操作都在内存中,所以Redis的速度非常快,性能十分强劲。 它...

    张迁 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<