JAVA学习记录(十五)—— 集合、范型、List

在这里插入图片描述

泛型:

  • 只存在于编译时期
  • 意义:自动进行类型的检查;自动进行类型的转换
  • 范式在编译的时候,并不会进行指定类型的替换,而是拿着指定的类型进行检查
  • 编译的时候,会进行类型擦除,编译的时候,编译都会把泛型擦除为Object,不是替换为Object。

  • 例:写一个通用的顺序表
class MyArrayList<T>{
    public T[] elem;
    public int usedSize;
 
    public MyArrayList(){
        // 不能直接new范型类,需要将Object向下类型转换为T类型的数组
        this.elem = (T[])new Object[10];
    }
    public void add(T data){
        this.elem[this.usedSize] = data;
        this.usedSize++;
    }
    public T get(int pos){
        return this.elem[pos];
    }

    public static void main(String[] args){
        // 简单类型不能做范型类型的参数 
        MyArrayList<String> myArrayList = new MyArrayList<>();  // 放字符型
        myArrayList1.add("abcd");
        myArrayList1.add("edfc");
        String str = myArrayList1.get(1);
        System.out.println(str); 
        
        MyArrayList<Integer> myArrayList2 = new MyArrayList<>(); // 放整形
        myArrayList2.add(1);
        myArrayList2.add(2);
        int val = myArrayList2.get(1);
        System.out.println(val);
        
        MyArrayList<Double> myArrayList3 = new MyArrayList<>();  // 放浮点型
        
    }
}
  • 1、class MyArrayList<T>,当中:表示占位符,表示当前这个类是一个泛型类
  • 2、简单类型不能做泛型类型的参数
  • 3、不能直接new泛型类型
  • 4、泛型类型的参数不参与类型的组成(泛型只是)

包装类

  • 装包/装箱操作:简单类型变为包装类
public static void main(String[] args) {
        int a = 10;
        Integer integer1 = new Integer(a);//显示的装包
        System.out.println(integer1);
        Integer integer2 = Integer.valueOf(a);//显示装包
        System.out.println(integer2);
        Integer integer3 = a;//自动装包,这种装包方法其实也是调用了Integer.valueOf
    }
  • 拆箱/拆包操作:包装类变为简单类型
public static void main(){
    Integer i = 10;
    int a= i;   // 自动拆箱 -> i.intValue()
    
    int a2 = i.intValue(); // 显示拆箱int
    
    double d = i.doubleValue(); // 拆成double类型
    
}
  • 一道面试题:代码如下会出现两种情况,如何解释?
public static void main(String[] args) {
        Integer a = 200;
        Integer b = 200;
        System.out.println(a == b);   // false
        
        Integer c = 100;
        Integer d = 100;
        System.out.println(c == d);   // true
    }
  • 解析:将简单类型装包Integer a = 200,底层会执行Integer.valueOf()方法,此方法如下:此处i就是200.
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
代码中 IntegerCache.low = -128
       IntegerCache.high = 127
所以 i 的取值只能在这之间

cache[] 是一个缓存数组 cache[]中存值的范围{-127 ~ 128}
  • 为什么要这样?如果i不在范围内,则就会new一个新的对象,但当在这个范围内时,取的数都是在这个数组内,所以比较的是数组内的值。源码这样设计是为了更高效,节省空间。

List的使用

  • 实现List的类ArrayList:
public static void main1(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        /*
          ArrayList底层是一个数组,每次放元素的时候
            放在了数组的最后。public boolean add(E e) {
             public void add(int index, E element) {
             这个方法是放在index位置
             问题:ArrayList底层是数组 那么他是多大??
             1、new ArrayList<>()  调用的是 不带有参数的构造方法
               那么大小默认为0。
             2、当调用饿了默认的构造方法之后,当你添加第一个元素的时候
             会进行扩容,第一次扩容的时候,大小为10;
             3、当后续进行扩容的时候 ,是进行了1.5倍的方式进行扩容
         */
        list.add(1);  
        System.out.println(list); // 输出:[1]

        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);

        list.addAll(arrayList);  // 在list的基础上插入一个arrayList
        System.out.println(list);// 输出为:[1,10,20]
        // T remove(int index)  删除index位置元素
        // boolean remove(Object o)   删除遇到的第一个o
        // 当给的是一个整形1,即int = 1,就会匹配到remove(int index)
        list.remove(0); // 删除0下标的值
        System.out.println(list); // 输出为:[10, 20]
        // 如果我想删除的是[1,10,20]中的1,而不是1下标
        // 所以要传入一个Object,传入Integer类
        Integer integer = 1;
        list.remove(integer);
        System.out.println(list);
        list.set(0,99); // 把0下标改为99
        System.out.println(list);
    }
  • subList需要注意的事项:
 public static void main2(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);
        
        List<Integer> list1 = new ArrayList<>();
        list1 = list.subList(1,3); //会提取1下标,2下标和3下标,输出为[2,3] ,返回值是一个List
        list1.set(0,88);          // 将list1的0下标改为88
        System.out.println(list1);// 则list1就变为了:[88,3]
        System.out.println(list); // 但list确也变成了[1,88,3,4,5]
        此处的subList是浅拷贝,并没有new新的对象
        在源码中时使用list1引用指向了list中的[2,3]部分
  • iterator迭代器:用来打印集合中的元素的
 public static void main2(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);//1 2 3 4 5

        //迭代器  用来打印集合中的元素的
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) { //hasNext,是否有下一个
        //iteerator 是在数组的前一个位置,所以打印的是iterator.next
            System.out.println(iterator.next());
        }
        // 慎用iterator.remove
        iterator.remove();  // 会删除最后一个数
        System.out.println(list);
}
  • 1、Java中,的集合类型包括ArrayList、LinkList、HashMap等,下列关于集合描述错误的是?(C)
A.ArrayList和LinkedList均实现了List接口
B.ArrayList的访问速度比LinkedList快
C.随机添加和删除元素时,ArrayList的表现更佳
D.HashMap实现Map接口,它允许任何类型的键和值对象

  解析:ArrayList是基于数组实现的,所以查询快,增删慢;LinkedList是基于链表实现的,所以查找慢,增删快。

*2、下列在Java语言中关于数据类型和包装类的说法,正确的是( B )

A.基本(简单)数据类型是包装类的简写形式,可以用包装类替代基本(简单)数据类型
B.longdouble都占了64位(64bit)的存储空间。
C.默认的整数数据类型是int,默认的浮点数据类型是float。
D.和包装类一样,基本(简单)数据类型声明的变量中也具有静态方法,用来完成进制转化等。
  • 解析:
    1、整数类型byte(1个字节)short(2个字节)int(4个字节)long(8个字节)
    2、字符类型char(2个字节)
    3、浮点类型float(4个字节)double(8个字节)

练习-创建一副扑克牌

public class pokerCard {
    public int rank;    // 牌面值
    public String suit; // 花色

    @Override
    public String toString() {
        return "[" +
                rank +","+
                suit +
                ']';
    }
}
public class CardDemo {
    // 扑克牌中花色是固定不变的,使用final修饰,
    public static final String[] SUITS = {"♦", "♥", "♣", "♠"};
    // 依据花色创建一副牌
    private static List<pokerCard> CreatPoker(){
        List<pokerCard> deck = new ArrayList<>(52); // 创建大小为52的数组来存放扑克牌
        for (int i = 0; i < 4; i++) { //遍历花色列表
            for(int j = 1; j <= 13; j++) {
                String suit = SUITS[i];
                int rank = j;
                pokerCard card = new pokerCard();
                card.rank = rank;
                card.suit = suit;

                deck.add(card); //将牌加入到扑克牌数组
            }
        }
        return deck;
    }
    // 洗牌
    public static void swap(List<pokerCard> deck, int i, int j){
        pokerCard t = deck.get(i);
        deck.set(i, deck.get(j));
        deck.set(j, t);
    }

    public static void Shuffle(List<pokerCard> deck){
        Random random = new Random(12);
        for (int i = deck.size() - 1; i >0 ; i--) {
            int r = random.nextInt(i);
            swap(deck, i, r);
        }
    }

    public static void main(String[] args) {
        // 创建poker
        List<pokerCard> deck = CreatPoker();
        System.out.println(deck);
        // 洗牌
        Shuffle(deck);
        System.out.println(deck);
        // 有三个人,每人拿五张牌
        List<List<pokerCard>> 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));
            }
        }

        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));
    }
}

练习-杨辉三角

  • 给定一个非负整数numRow,实现杨辉三角前numRows行。杨辉三角中,每个数是它左上方和右上方的数之和。
public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<>();
        if(numRows <= 0) return ret;
        //第一行的list
        List<Integer> list = new ArrayList<>();
        list.add(1);
        //把第一行的list放到ret当中
        ret.add(list);
        for(int i = 1;i < numRows;i++) {
            List<Integer> curRow = new ArrayList<>();
            curRow.add(1);
            for(int j = 1 ;j < i;j++) {
                //确定的是当前行的每个元素  ==  上一行的当前列+上一行的前一列就是我当前需要添加的数字
                List<Integer> preRow = ret.get(i-1);
                int num = preRow.get(j-1)+preRow.get(j);
                curRow.add(num);
            }
            //手动在当前行的最后一个位置 添加一个1
            curRow.add(1);
            ret.add(curRow);
        }
        return ret;
    }
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值