014泛型、接口、LinkedList、ArrayList

1.泛型

1.1概念

public class LinkedList extends
Abstract Sequential implements List
public interface Deque extends Queue { }
public interface Queue extends Collection { }
public interface Collection extends Iterable { }
上面的代码中出现的<?>是泛型,常用来和集合对象一同使用,所以在开始学习集合之前,必须先了解一下什么是泛型。而且泛型的概念非常重要,它是程序的增强器,它是目前主流的开发方式。
泛型是JDK1.5提供的新特性,其实就是一个【语法糖】,本质上就是编译器为了提供更好的可读性而提供的一种小技巧,虚拟机层面是不存在所谓的泛型概念的。

1.2作用

通过泛型的语法定义<>,约束集合元素的类型,编译器可以在编译器提供一定的安全检查,这样可以避免运行时候才暴露bug,代码的通用性也会更强,泛型可以提升代码的可读性,但是它只是一个“语法糖”(编译后这样的部分会被删除,不会出现在源码中,所以不会影响JVM后期运行时的性能)

1.3泛型实例

实例1:我们创建一个ArrayList,看到界面上会有一个黄线警告,是为什么呢?
原因:ArrayList定义时候使用了泛型,在声明泛型时候需要制定具体的额类型
我们把这个“<>”方式称之为泛型,那么泛型有什么样的作用呢?就是在啊编译检查阶段检查传入的参数是否正确。
有了泛型,我们可以看到要求存放的是String类型,而测试存放的是int类型的100,所以eclipse会报错:
类型list 的add方法要求添加的类型为String类型,int类型不匹配,不能正确存入。

1.4泛型声明

泛型可以在接口、类、方法上使用

public interface Collection{}
public class TestStudy{}
public void print (E e){}
在方法返回值前声明一个,表示后面出现的E是泛型,而不是普通的Java变量

1.5常用名词

E - Element 在集合中使用,因为集合中存放的是元素
T - Type Java类
K - Key 键
V - value 值
N - number 数值类型
?- 表示不确定的Java类型

1.6泛型测试

package day14;

import java.util.ArrayList;

/**
 * 本类用于测试泛型的优点
 */
public class Test1_Generic {
    public static void main(String[] args) {
        //1.泛型是怎么来的:想要模仿数组的数据类型检查
        String[] a = new String[5];
        a[2] = "马乐乐";
        a[3] = "龙王爷";
        //a[0] = 100;数组的好处,在编译时期检查数据的类型,如果不是要求的数据类型就会在编译器时期报错

        //2.泛型通常会结合着集合一起使用
        ArrayList<Object> list = new ArrayList<>();
        list.add("白龙马");
        list.add(18);
        list.add('a');
        list.add(2.2);
        System.out.println(list);

        //3.引入泛型--主要目的是想约束集合中元素的类型<?>
        //4.泛型的好处:可以把报错的时机提前,在编译器就报错,而不是在运行后抛出异常,
        // 在向集合中添加元素时,会先检查元素的数据类型,不是要求的数据类型就会编译失败
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("小龙女");
//        list1.add(18);存入的是Integer类型,会报错
//        list1.add(2.3);存入的是Double类型,会报错
//        list1.add('a');存入的是Character类型,会报错

        //5.<type>---type的值应该如何写?
        //需要查看存放的数据类型是什么,根据类型进行定义
        //注意这里Type的类型必须是引用类型不能是基本类型
//       new ArrayList<int>();会报错:Type argument cannot be of primitive type
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(222);
        list2.add(333);
        list2.add(666);
        System.out.println(list2);
    }
}

1.7练习:泛型测试2

package day14;

public class Test2_Generic2 {
    public static void main(String[] args) {
        Integer[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        print(a);

        String[] b = {"林黛玉", "贾宝玉", "施耐庵", "林冲"};
        print(b);

        Double[] c = {2.1, 2.2, 2.3, 2.4};
        print(c);
    }

    public static <E> void print(E[] e) {
        //泛型的语法要求:如果在方法上面使用泛型,需要两处同时出现,
        //一个是在传入的参数类型,一个是返回值前的类型,表示这是一个泛型
        for (E d : e) {
            System.out.println(d);
        }
    }


//    public  static void print(Double[] c) {
//        for (Double d:c) 
//        {
//            System.out.println(d);
//        }
//    }
//
//    public static void print(String[] b) {
//        for (String s:b) 
//        {
//            System.out.println(b); 
//        }
//    }
//
//    public static void print(Integer[] a) {
//        for (Integer i:a) {
//            System.out.println(i);
//        }
}

2.Collection接口

Java的语言中Util包中提供了一些集合类,这些集合类由称之为容器,提到容器不难想到数组,集合类和数组最主要的不同之处在于,数组的长度是固定的,集合的长度是可变的,数组的访问方式比较单一,插入、删除等操作比较繁琐,而集合的访问方式比较灵活,常用的集合类有list集合,Set集合,Map集合,其中Set集合和List集合继承了Collection接口,各个接口还提供了不同的实现类。

2.1概述

集合的英文名称是Collection,用来存放对象的数据结构,而且长度可变,可以存放不同类型的独享,并且还提供了一组操作成批对象的方法。Collection接口层次结构中的根接口,接口不能直接使用,但是该接口提供了添加元素、删除元素、管理元素的父类接口公共方法。
由于List接口与set接口都继承了Collection接口,因此这些方法对于List集合和Set集合都是通用的。

2.2 集合的集成结构

Collection接口
—List接口:数据有下标,所以数据是有序的,可以重复存数值
—ArrayList子类
—LinkedList子类
—Set接口:数据是没有下标的,所以数据是无序的,不可以存重复的值
—HashSet子类
Map接口:键值对的方式存数据(注意:Map是一种接口,是和Collection同层级的,并不是collection子接口)
—HashMap

2.3常用方法速查表

2.4练习:Collection接口

package day14;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

public class Test3_Collection {
    public static void main(String[] args) {
//        Collection collection = new Collection<>();
        //Collection是接口不能直接实例化
        ArrayList<Integer> c = new ArrayList<>();
        c.add(100);
        c.add(200);
        c.add(300);
        c.add(400);
        c.add(500);
        System.out.println(c);
       // c.clear();清除c中所有元素
       // System.out.println(c);

        System.out.println(c.contains(100));
        System.out.println(c.isEmpty());
        System.out.println(c.remove(1));
        System.out.println(c);
        System.out.println(c.size());
        System.out.println(c.equals(200));
        Object [] array = c.toArray();
        System.out.println(Arrays.toString(array));

        Collection<Integer> c2 = new ArrayList<Integer>();

        c2.add(2);
        c2.add(3);
        c2.add(5);
        System.out.println(c2);//[2, 3, 5]

        c.addAll(c2);
        System.out.println(c);//[100, 300, 400, 500, 2, 3, 5]
        System.out.println(c2);//[2, 3, 5]
        System.out.println(c.containsAll(c2));//true
        System.out.println(c.contains(c2));//false,判断C中是否有C2这个元素
        System.out.println(c.removeAll(c2));//true
        System.out.println(c.containsAll(c2));//false

        //使用迭代器来遍历元素
        Iterator<Integer> it = c.iterator();
        while (it.hasNext()){
            System.out.println(it.next());//输出c中所有元素
        }
    }
}

3.List接口

3.1概述

有序的collection(也称为序列),此接口的用户可以对列表中的每个元素插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素。

3.2特点

  • 元素都有下标
  • 数据是有序的
  • 允许存放重复的元素

3.3常用方法速查表

3.4练习:List接口测试

package day14;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test4_List {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("大公主红红");
        list.add("二公主橙橙");
        list.add("三公主黄黄");
        list.add("四公主绿绿");
        list.add("五公主青青");
        list.add("六公主蓝蓝");
        list.add("七公主紫紫");
        System.out.println(list);//[大公主红红, 二公主橙橙, 三公主黄黄, 四公主绿绿, 五公主青青, 六公主蓝蓝, 七公主紫紫]
//        list.clear();//清空集合
//        System.out.println(list);//[]
        System.out.println("----------------------------------");
        System.out.println(list.contains("董勇"));//false
        System.out.println(list.equals("大公主红红"));//false
        System.out.println(list.hashCode());//-49722495
        System.out.println(list.get(3));//四公主绿绿,按照索引来获取元素
        System.out.println(list.remove("大公主红红"));
        System.out.println(list);//[二公主橙橙, 三公主黄黄, 四公主绿绿, 五公主青青, 六公主蓝蓝, 七公主紫紫]
        System.out.println(list.remove(0));
        System.out.println(list);//[三公主黄黄, 四公主绿绿, 五公主青青, 六公主蓝蓝, 七公主紫紫]
        //对比上面两个方法可以看出remove在使用String的时候,即可以用index方式按照下标移除
        //也可以用“String”里面的字符串内容做匹配来进行移除
        System.out.println(list.size());//5
        System.out.println(Arrays.toString(list.toArray()));//转化为字符串

        list.add("土地老儿");
        System.out.println(list);//尾部追加//[三公主黄黄, 四公主绿绿, 五公主青青, 六公主蓝蓝, 七公主紫紫, 土地老儿]
        list.add(1, "龙太子");
        System.out.println(list);//指定位置添加//[三公主黄黄, 龙太子, 四公主绿绿, 五公主青青, 六公主蓝蓝, 七公主紫紫, 土地老儿]
        list.add(4, "龙太子");
        System.out.println(list);//指定位置添加已存在元素//[三公主黄黄,龙太子,四公主绿绿,五公主青青,龙太子,六公主蓝蓝,七公主紫紫,土地老儿]
        list.set(2, "白龙马");
        System.out.println(list);//[三公主黄黄, 龙太子, 白龙马, 五公主青青, 龙太子, 六公主蓝蓝, 七公主紫紫, 土地老儿]
        System.out.println(list.indexOf("龙太子"));//1
        System.out.println(list.lastIndexOf("龙太子"));//4
        List<String> list2 = list.subList(2, 6);
        System.out.println(list2);//[白龙马, 五公主青青, 龙太子, 六公主蓝蓝]

        System.out.println(list.contains(list2));//false
        System.out.println(list.containsAll(list2));//true
        System.out.println(list.removeAll(list2));//true
        System.out.println(list);//[三公主黄黄, 七公主紫紫, 土地老儿]
    }
}

3.5练习:List接口测试2

package day14;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

public class Test5_List2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("大叔");
        list.add("二叔");
        list.add("三叔");
        list.add("四叔");
        list.add("五叔");
        list.add("六叔");
        list.add("七叔");

        //方式1:测试循环迭代,因为元素下标有序,根据下标循环
        for (int i = 0; i < list.size(); i++) {
            String string = list.get(i);
            System.out.print(string);
        }
        System.out.println("-----------");

        //方式2:高效for循环
        for (String s:list) {
            System.out.print(s);
        }
        System.out.println("-----------");
        //方式3:list迭代器
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next());
        }
        System.out.println("----------");
        //方式4:ArrayList迭代器
        ListIterator<String> iterator1 = list.listIterator();
        while (iterator1.hasNext()){
            System.out.print(iterator1.next());
        }
        /**
         *   思考:方式3和方式4有什么不同
         *   3使用的是父接口中的iterator,4使用的是子接口中的iterator
         *   子接口拥有父接口中的所有方法,初次之外,子接口也可以拥有自己特有的方法
         */
    }
}

4.ArrayLi

4.1 概述

  1. 存在于java.util包中
  2. 内部是用于数组结构存放数据,封装数组的操作,每个对象都有下标
  3. 内部数组默认的初试容量是10,如果不够会以1.5倍的容量增长
  4. 查询快,增删效率比较低

4.2创建对象

ArrayLi()创建一个初试容量为10的空序列
源码摘抄:int newCapacity = oldCapacity + (oldCapacity >> 1);
解释:数组的新容量=旧容量 /2的一次方----相当于原来的1.5倍的扩容(找时间把这里的源码再锊一边)

4.3练习:ArrayList数组

package day14;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

public class Test6_ArrayList {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(100);
        list.add(400);
        list.add(200);
        list.add(300);
        list.add(0, 700);//[700, 100, 200, 300, 100, 400, 200, 300]
        System.out.println(list);

//        list.clear();
//        System.out.println(list);//[]
        System.out.println(list.contains(200));//true
        System.out.println(list.get(0));//700
        System.out.println(list.indexOf(100));//1
        System.out.println(list.lastIndexOf(100));//4
        System.out.println(list.isEmpty());//false
        System.out.println(list.set(0, 666));//true
        System.out.println(list);//[666, 100, 200, 300, 100, 400, 200, 300]
        System.out.println(list.remove(1));
        System.out.println(list);//[666, 200, 300, 100, 400, 200, 300]
//        System.out.println(list.remove(200));会报错,根据下标来移除
        System.out.println(list.remove(Integer.valueOf(200)));//true
        System.out.println(list);//[666, 300, 100, 400, 200, 300],按照从前到后的下标移除

        //循环方式1
        for (int i = 0; i < list.size(); i++) {
            Integer integer = list.get(i);
            System.out.println(integer);
        }

        //循环方式2
        for (Integer i : list) {
            System.out.println(i);
        }

        //循环方式3
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        //循环方式4
        ListIterator<Integer> iterator1 = list.listIterator();
        while (iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
    }
}

7 LinkedList

7.1 概述

链表,两端效率高,底层就是链表实现的

总结:
ArrayList底层是数组结构,查询快,增删慢,适合查询比较多的业务场景
LinkedList底层是链表结构,查询慢,增删快,适合增删比较多的业务场景
注意:LinkedList查询慢是指业务数据量 比较大的时候,查询中间比较慢,首尾操作还是比较快的

7.2创建对象

LinkedList()构造一个空列表

7.3常用方法

Void add First(E e)将指定元素插入此列表的开头
Void add Last(E e)将指定元素插入此列表的结尾
E. getFirst() 返回此列表的第一个元素
E.getLast ( ) 返回此列表的最后一个元素
E. removeFirst() 移除此列表的第一个元素
E. removelast() 移除此列表的最后一个元素
E element ( ) 获取但不移除此列表的头(第一个元素)
boolean offer( E e)将指定元素添加到此列表的末尾(最后一个元素)
boolean offerFirst ( E e)在此列表的开头插入指定的元素
boolean offerLast(E e)在此列表的末尾插入指定的元素
E peek() 获取但不移除此列表的头(第一个元素)
E peekFirst() 获取但不移除次列表的尾(最后一个元素)
E pollFirst()获取并移除此列表的第一个元素;如果此列表为空,则返回null
E pollLast()获取并移除此列表的最后一个元素;如果此列表为空,则返回null

7.4: LinkedList测试

package day14;


import java.util.LinkedList;

public class Test7LinkedList<S> {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();

        list.add("林黛玉");
        list.add("贾宝玉");
        list.add("薛宝钗");
        list.add("史湘云");
        list.add("呆霸王");
        list.add("贾祖母");
        System.out.println(list);//[林黛玉, 贾宝玉, 薛宝钗, 史湘云, 呆霸王, 贾祖母]

        list.addFirst("晴雯");
        System.out.println(list);//[林黛玉, 贾宝玉, 薛宝钗, 史湘云, 呆霸王, 贾祖母]
        list.addLast("雪雁");
        System.out.println(list);//[晴雯, 林黛玉, 贾宝玉, 薛宝钗, 史湘云, 呆霸王, 贾祖母, 雪雁]
        System.out.println(list.removeFirst());//晴雯
        System.out.println(list);//[林黛玉, 贾宝玉, 薛宝钗, 史湘云, 呆霸王, 贾祖母, 雪雁]
        System.out.println(list.removeLast());
        System.out.println(list);//[林黛玉, 贾宝玉, 薛宝钗, 史湘云, 呆霸王, 贾祖母]

        LinkedList list1 = new LinkedList();
        list1.add("飘");
        list1.add("红与黑");
        list1.add("救赎");
        list1.add("茶花女");
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女]

        System.out.println(list1.element());//飘
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女]

        System.out.println(list1.peek());//飘
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女]
        System.out.println(list1.peekFirst());//飘
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女]
        System.out.println(list1.peekLast());//茶花女
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女]

        System.out.println(list1.offer("基督山伯爵"));//true
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女, 基督山伯爵]
        System.out.println(list1.offerFirst("海底两万里"));//true
        System.out.println(list1);//[海底两万里, 飘, 红与黑, 救赎, 茶花女, 基督山伯爵]
        System.out.println(list1.offerLast("李尔王"));
        System.out.println(list1);//[海底两万里, 飘, 红与黑, 救赎, 茶花女, 基督山伯爵]


        System.out.println(list1.poll());//海底两万里
        System.out.println(list1);//[飘, 红与黑, 救赎, 茶花女, 基督山伯爵, 李尔王]
        System.out.println(list1.pollFirst());//飘
        System.out.println(list1.pollLast());//李尔王
        System.out.println(list1);//[红与黑, 救赎, 茶花女, 基督山伯爵]
        
    }
}

8 扩展

ArrayList扩容
ArrayList相当于在没指定initalcapacity时就是会延时分配对象数组,当第一次插入元素时候才会分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,将ArrayList的容量变为10,之后扩容会按照1.5倍增长,也就是当添加第11个元素的时候,ArrayList会继续扩容变成101.5=15,当添加第16个元素的时候,继续扩容为151.5 = 22个,以此类推。
ArrayList没有对外暴露其容量个数,查看源码我们知道,实际其值存放在elementDate对象数组中,那么我们只需要拿到这个数组的长度,观察其值变化了几次就知道扩容了几次,可以用反射技术获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值