Java---集合Collection--List

1 概述

英文名称Collection,是用来存放对象的数据结构。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。

数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。

2 集合的继承结构

在这里插入图片描述

Collection接口

– List接口 : 数据有序,可以重复。

– ArrayList子类

– LinkedList子类

– Set接口 : 数据无序,不可以存重复值

– HashSet子类

– Map接口 : 键值对存数据

– HashMap

Collections工具类

3 常用方法

boolean add(E e):添加元素。

boolean addAll(Collection c):把小集合添加到大集合中 。

boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。

boolean isEmpty() :如果此 collection 没有元素,则返回 true。

Iterator iterator():返回在此 collection 的元素上进行迭代的迭代器。

boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。

int size() :返回此 collection 中的元素数。

Objec[] toArray():返回对象数组

4 demo1:测试常用方法

import java.util.ArrayList;

import java.util.Collection;

import java.util.Iterator;

public class Test_301_Collection {

       public static void main(String[] args) {

              Collection c = new ArrayList();//接口无法直接创建对象

              c.add("hello");//添加元素

              c.add("java");//添加元素

              c.add("~");//添加元素

              c.add(10);//jdk5后有自动装箱功能,相当于把10包装Integer.valueOf(10)

              System.out.println(c.remove("~"));//移除元素

              System.out.println(c.contains("a"));//判断包含关系

              System.out.println(c.size());//集合的长度

              System.out.println(c);

             

              //for遍历集合

              for(int i =0 ;i<c.size();i++) {

                     System.out.println(c.toArray()[i]);

              }

              //iterator迭代器遍历

              Iterator it = c.iterator();//对 collection 进行迭代的迭代器

              while (it.hasNext()) {//如果仍有元素,则返回 true

                     System.out.println(it.next());//返回迭代获取到的下一个元素

              }   } }

5 List接口

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

5.2 特点

1、 数据有序

2、 允许存放重复元素

3、 元素都有索引

5.3 常用方法
ListIterator listIterator()

      返回此列表元素的列表迭代器(按适当顺序)。

ListIterator listIterator(int index)

      返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

void add(int index, E element)

      在列表的指定位置插入指定元素(可选操作)。

boolean addAll(int index, Collection<? extends E> c)

      将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

List subList(int fromIndex, int toIndex)

 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

E get(int index)

      返回列表中指定位置的元素。  

int indexOf(Object o)

      返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

5.4 demo1:测试常用方法

package cn.tedu.list;


import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import java.util.ListIterator;

 

//这类用来测试List接口的常用方法

public class Test1_List {

 

    public static void main(String[] args) {

       //1、创建List对象

       //特点1:List集合元素都有索引,可以根据索引直接定位元素

       List list = new ArrayList();

      

       //2、常用方法

       list.add(111);

       list.add(222);

       list.add(333);

       list.add(444);

       list.add('a');

       list.add("abc");

      

       list.add(3,666);//在3的索引处添加指定元素

 

       //特点2:元素有序, 怎么存就怎么放

       System.out.println(list);//[111, 222, 333, 666, 444, a, abc]

      

       Object obj = list.get(4);//get(m)-m是索引值,获取指定索引位置的元素

       System.out.println(obj);

      

      

       //3、迭代/遍历集合中的元素

       //使用Collection接口提供的iterator()

       Iterator it = list.iterator();

       while(it.hasNext()) {//判断集合里有没有下个元素

           Object o = it.next();

//         System.out.println(o);

       }

      

       //使用List接口提供的listIterator()

       //interfaceListIterator extends Iterator

       //区别:可以使用父接口的功能,同时拥有自己的特有功能,不仅顺序向后迭代还可以逆向迭代

       ListIterator it2 = list.listIterator();

       while(it2.hasNext()) {

           Object o = it2.next();

//         System.out.println(o);

       }
 

       System.out.println();

      
       List list2 = list.subList(1, 3);//subList(m,n)-m是开始索引,n是结束索引,其中含头不含尾类似于String.subString(m,n)

       System.out.println(list2);
    

    }
   
}

5.5 ArrayList

5.5.1 概述

  1. 存在于java.util包中。
    
  2. 内部用数组存放数据,封装了数组的操作,每个对象都有下标。
    
  3. 内部数组默认初始容量是10。如果不够会以1.5倍容量增长。
    

在这里插入图片描述
在这里插入图片描述

  1. 查询快,增删数据效率会降低。
    

5.5.2 创建对象

new ArrayList():初始容量是10

5.5.3 demo1:测试常用方法

常用API,包括下标遍历,迭代器遍历

import java.util.ArrayList;

public class Test3_AL {

       public static void main(String[] args) {

              ArrayList list = new ArrayList();

              list.add("aaa");//存入数据

              list.add("123");

              list.add("ccc");

              list.add("ddd");

              System.out.println(list);//list中内容

              System.out.println(list.size());//集合长度

              System.out.println(list.get(1));//根据下标获取元素

                    

              System.out.println();

              System.out.println(list.remove(2));//移除下标对应的元素

              System.out.println(list);

                    

                     //下标遍历

                     for (int i = 0; i < list.size(); i++) {

                            System.out.print(list.get(i));

                     }

 

       //Iterator迭代遍历,封装了下标

                     Iterator<String> it = list.iterator();

                     while (it.hasNext()) {//如果有数据

                            String s = it.next();//一个一个向后遍历

                            System.out.println(s);

                     }     

              }

}

5.2 LinkedList

5.2.1 概述
双向链表,两端效率高。底层就是数组和链表实现的。

在这里插入图片描述

5.2.3 常用方法

add()

get()

size()

remove(i)

remove(数据)

iterator()

addFirst() addLast()

getFirst() getLast()

removeFirst() removeLast()

5.2.4 demo1:测试迭代器遍历
双向链表:下标遍历效率低,迭代器遍历效率高

> import java.util.ArrayList;
> 
> import java.util.Iterator;
> 
> import java.util.LinkedList;
> 
>  
> 
> public class tt {
> 
>        public static void main(String[] args) throws Exception {
> 
>               LinkedList ll = new LinkedList ();
> 
>               for (int i = 0; i < 100000; i++) {
> 
>                      ll.add(100);
> 
>               }
> 
>               f1(ll);
> 
>               f2(ll);
> 
>        }
> 
>  
> 
>        private static void f2(LinkedList<Integer> ll) {
> 
>               long t = System.currentTimeMillis();
> 
>               Iterator it = ll.iterator();
> 
>               while(it.hasNext()) {
> 
>                      it.next();
> 
>               }
> 
>               t = System.currentTimeMillis()-t;
> 
>               System.out.println("=====iterator========="+t);//16
> 
>        }
> 
>  
> 
>        private static void f1(LinkedList<Integer> ll) {
> 
>               long t = System.currentTimeMillis();
> 
>               for (int i = 0; i < ll.size(); i++) {
> 
>                      ll.get(i);
> 
>               }
> 
>               long t1 = System.currentTimeMillis();
> 
>               System.out.println("~~~~for~~~~~~~"+(t1-t));//9078
> 
>        }
> 
> }

5.3 ArrayList扩容

ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,将ArrayList的容量变为10 (如下图一);之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15(如下图二);当添加第16个数据时,继续扩容变为15 * 1.5 =22个

在这里插入图片描述

ArrayList没有对外暴露其容量个数,查看源码我们可以知道,实际其值存放在elementData对象数组中,那我们只需拿到这个数组的长度,观察其值变化了几次就知道其扩容了多少次。怎么获取呢?只能用反射技术了。

5.4 HashMap扩容

成长因子:

static final float DEFAULT_LOAD_FACTOR = 0.75f;

前面的讲述已经发现,当你空间只有仅仅为10的时候是很容易造成2个对象的hashcode 所对应的地址是一个位置的情况。这样就造成 2个 对象会形成散列桶(链表)。这时就有一个加载因子的参数,值默认为0.75 ,如果你hashmap的 空间有 100那么当你插入了75个元素的时候 hashmap就需要扩容了,不然的话会形成很长的散列桶结构,对于查询和插入都会增加时间,因为它要一个一个的equals比较。但又不能让加载因子很小,如0.01,这样显然是不合适的,频繁扩容会大大消耗你的内存。这时就存在着一个平衡,jdk中默认是0.75,当然负载因子可以根据自己的实际情况进行调整。

5.5 数组和链表区别

List是一个接口,它有两个常用的子类,ArrayList和LinkedList,看名字就可以看得出一种是基于数组实现另一个是基于链表实现的。

数组ArrayList遍历快,因为存储空间连续;链表LinkedList遍历慢,因为存储空间不连续,要去通过指针定位下一个元素,所以链表遍历慢。

数组插入元素和删除元素需要重新申请内存,然后将拼接结果保存进去,成本很高。例如有100个值,中间插入一个元素,需要数组重新拷贝。而这个动作对链表来说,太轻松了,改变一下相邻两个元素的指针即可。所以链表的插入和修改元素时性能非常高。

实际开发就根据它们各自不同的特点来匹配对应业务的特点。业务一次赋值,不会改变,顺序遍历,就采用数组;业务频繁变化,有新增,有删除,则链表更加适合。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值