Java基础(00)容器


容器

一 泛型

  • 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

1、泛型方法

  • 泛型方法的定义规则
    • 在方法返回值之前,多个类型参数()间用逗号隔开。
    • 返回值类型可以用泛型声明,方法内,泛型可以当作正常的类来使用。
    • 泛型只能代表引用型类型,不能是基本类型。
public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}
  • 有界的类型参数
    • 上界 <? extends Fruit> ,表示所有继承Fruit的子类,包含Fruit本身
    • 下界 <? super Apple>,表示Apple的所有父类,包含Apple本身

2、 泛型类

  • 类名后添加类型参数声明,泛型接口使用基本和泛型类差不多
public class Box<T> {
   
  private T t;
 
  public void add(T t) {
    this.t = t;
  }
 
  public T get() {
    return t;
  }
 
  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String> stringBox = new Box<String>();
 
    integerBox.add(new Integer(10));
    stringBox.add(new String("菜鸟教程"));
 
    System.out.printf("整型值为 :%d\n\n", integerBox.get());
    System.out.printf("字符串为 :%s\n", stringBox.get());
  }
}

3、 伪泛型的概念

  • 泛型只在源码中存在,在编译后的字节码中就已经替换为原来的原生类型了,并且在相应的地方插入了强制类型转换的代码,Java的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型

二、容器(集合)概述

1、Java集合框架的体系结构:

在这里插入图片描述

说明
  • 所有的集合框架体系都包含:接口、实现类和算法
  • collection 接口所包含的方法:
    在这里插入图片描述

三、list

  • List 的特点是:元素有序排列且可重复

1、常用方法

在这里插入图片描述

两个 list 之间的元素操作
  • list.containsAll(list2)-------list是否包含list2中所有元素
  • list.addAll(list2)--------将list2中所有元素都添加到list中
  • list.removeAll(list2)--------从list中删除同时在list和list2中存在的元素
  • list.retainAll(list2)-------取list和list2的交集

2、ArrayList

  • 特点:查询效率高,增删效率低,线程不安全
  • 原理:ArrayList底层使用Object数组来存储元素数据,超出数组默认长度重新搞一个更大的数组,然后将已有内容复制过去

3、LinkedList

  • 特点:查询效率低,增删效率高,线程不安全
  • 原理:每个数据节点中都有两个指针,分别指向前一个节点和后一个节点
    在这里插入图片描述

4、Vector

  • 和 arraylist 相比,线程安全,效率低,几乎不用了

5、List应用总结

  • 不存在线程安全问题时,并且查找较多用ArrayList(一般使用它)
  • 不存在线程安全问题时,增加或删除元素较多用LinkedList

四、queue

  • 描述:特殊的线性表,特点是先进先出
  • 方法:
    • offer()来加入元素 poll()来获取并移出元素
    • element()或者peek()方法使用前端而不移出该元素
  • 注意:LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用
public class QueueTest {
    public static void main(String[] args) {
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
        
    }
}

四、map

1、概述

  • Map就是用来存储 键(key)-值(value) 对 的,键不能重复
  • Map 接口的实现类有 HashMap、TreeMap、HashTable、Properties 等

2、map接口方法

在这里插入图片描述

3、HashMap和HashTable

  • 原理:HashMap采用哈希算法实现,底层采用了哈希表存储数据,键不能重复,如果发生重复,新的会替换旧的
  • 特点:HashMap在查找、删除、修改方面都有非常高的效率
  • 区别:
    • HashMap: 线程不安全,效率高。允许key或value为null
    • HashTable: 线程安全,效率低。不允许key或value为null

4、HashMap底层实现详解

数据结构中由数组和链表来实现对数据的存储
  • 数组:占用空间连续。 寻址容易,查询速度快。但是,增加和删除效率非常低。
  • 链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。
  • 哈希表的本质就是 数组+链表,集合二者优点。
HashMap的结构
  • Entry[] table 就是HashMap的核心数组结构,称之为 位桶数组;
  • 一个Entry对象存储了: key对象 ;value对象 ;下一个节点next ;键的hash值;
    在这里插入图片描述
存数据过程
  • 首先调用key对象的hashcode()方法,获得hashcode;
  • 根据hashcode计算出hash值,要求转化后的hash值尽量均匀地分布在[0,数组长度-1]这个区间,减少hash冲突;
  • 生成Entry对象,将Entry对象放到table数组中:如果本Entry对象对应的数组索引位置还没有放Entry对象,则直接将Entry对象存储进数组,如果对应索引位置已经有Entry对象,则将已有Entry对象的next指向本Entry对象,形成链表;
  • hash算法采用 hashcode与(length-1)的位与运算;链表长度大于8时,链表就转换为红黑树,提高了查找效率;
取数据过程
  • 通过 key的hashcode 得到 hash 值,通过这个值找到数组的位置;
  • 然后在对应的链表上调用 key的 equals 方法逐一与所有节点的 key比较;
  • 返回比较后为 true 的节点对应的 value 值;
  • Java中规定,两个内容相同(equals()为true)的对象必须具有相等的hashCode,否则Map取数据的过程存在悖论;
扩容
  • HashMap的位桶数组,初始大小为16,大小是可变的,如果位桶数组中的元素达到(0.75*数组 length), 就重新调整数组大小变为原来2倍大小;
  • 扩容的本质是定义新的更大的数组,并将旧数组内容挨个拷贝到新数组中,很耗时;

5、TreeMap

二叉树
  • 基本二叉树
  • 排序二叉树
    • 左子树上所有节点的值均小于它的根节点的值
    • 右子树上所有节点的值均大于它的根节点的值
  • 平衡二叉树
    • 在平衡二叉树中任何节点的两个子树的高度最大差别为1
    • 平衡二叉树建立在排序二叉树的基础上,通过左旋或者右旋的操作来达到平衡
  • 红黑二叉树:自平衡的排序二叉树
TreeMap的底层实现
  • TreeMap是红黑二叉树的典型实现;
  • entry 里面存储了本身数据、左节点、右节点、父节点、以及节点颜色;
TreeMap的使用
  • HashMap效率高于TreeMap,一般用他;
  • 在需要排序的Map时才选用TreeMap;

五、set

1、概述

  • Set容器特点:无序、不可重复(null 值也只能有一个);
  • Set常用的实现类有:HashSet、TreeSet等,一般使用HashSet;

2、HashSet

  • 使用:使用时注意无序和不可重复的特点
  • 底层实现:HashSet本质就是一个简化版的HashMap,数据存到键对象

3、TreeSet

使用:
  • 对应的类需要实现Comparable接口,才能根据compareTo()方法比较对象之间的大小,才能进行内部排序;TreeSet中不能放入null元素;
@Override
public int compareTo(User o) {
     if (this.id > o.id) {
         return 1;
     } else if (this.id < o.id) {
         return -1;
     } else {
         return 0;
     }
 }
底层实现:
  • 一个简化版的TreeMap,通过key来存储Set的元素

六、迭代器

1、迭代器

  • 一般情况集合在遍历的过程中是不许删除操作的会报错,但是使用迭代器可以实现
Set<String> set = new HashSet<>();
set.add("haha1");
set.add("haha2");
set.add("haha3");
set.add("haha4");
Iterator<String> ite = set.iterator();
while(ite.hasNext()){
	String str = ite.next();
	if(str.endsWith("3")){
		ite.remove();
	}
	System.out.print(str+"\t");
}
System.out.println();
for (String str:set) {
	System.out.print(str+"\t");
}
常用集合的遍历
  • List:普通for,增强for和迭代器
  • set:增强for和迭代器
  • map:增强for和迭代器(keys,values,keyset,entryset)

2、Collections工具类

  • Collections 提供了对Set、List、Map进行排序、填充、查找元素的辅助方法
    • void sort(List)---------对List容器内的元素排序,排序的规则是按照升序进行排序
    • void shuffle(List)-----------对List容器内的元素进行随机排列
    • void reverse(List)-----------对List容器内的元素进行逆续排列
    • void fill(List, Object)-----------用一个特定的对象重写整个List容器
    • int binarySearch(List, Object)-----------对于顺序的List容器,采用折半查找的方法查找特定对象
  • 如下情况可能需要重写 equals/hashCode 方法
    • 要将我们自定义的对象放入HashSet中处理
    • 要将我们自定义的对象作为HashMap的key处理
    • 放入Collection容器中的自定义对象后,可能会调用remove、contains等方法时

七、Java数据结构

  • Java中的数据结构主要包括以下几种接口和类:
  • 枚举(Enumeration)
  • 位集合(BitSet):保存位值的特殊数组,有许多位操作的方法
  • 向量(Vector):几乎不用这个了
  • 栈(Stack)
  • 字典(Dictionary):存储键值对,类似于Map,已过时
  • 哈希表(Hashtable):几乎不用了
  • 属性(Properties)
栈(Stack)
  • 特点是后进先出,是Vector的一个子类,常用的方法:
    • boolean empty( )
    • Object peek( )
    • Object pop( )
    • Object push(Object element)
    • int search(Object element)
属性(Properties)
  • HashTable的子类,存键值对,键和值都是String,常用来配合IO流加载配置文件,常用方法如下:
void load(InputStream streamIn) throws IOException //从输入流中读取属性列表(键和元素对)
void store(OutputStream streamOut, String description)//将此Properties中的属性列表(键和元素对)写入输出流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值