Java学习十六天(集合概述,ArrayList底层,LinkedList底层,List扩展方法,泛型)

集合存储的是元素的地址。

package com.bjsxt.collection;
import com.bjsxt.demo.Gender;
import com.bjsxt.demo.Person;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
public class Test {
    public static void main(String[] args) {
        Collection collection=new ArrayList();//接口new实现类
        System.out.println("集合是否为空:"+collection.isEmpty());
        //(1)添加元素
        collection.add("hello");
        collection.add(new Date());
        collection.add(123);
        collection.add("hello");
        collection.add(new Person("lisli",29, Gender.男));
        System.out.println("集合是否为空:"+collection.isEmpty());
        System.out.println("集合中元素的个数:"+collection.size());
        System.out.println(collection);
        System.out.println(collection.remove("hello")); //将第一个hello删除
        //collection.clear();
        System.out.println(collection);
        System.out.println(collection.contains(123));
        Collection collection1=new ArrayList();
        collection1.add("world1");
        collection1.add("world2");
        collection1.add("world3");
        collection.addAll(collection1);
        System.out.println(collection);
        //遍历集合
        System.out.println("---------------------------------------");
        for(Object obj:collection){
            System.out.println(obj);//默认调用toString()方法
        }
        System.out.println("------------------自己使用迭代器遍历元素 hasNext() ,next()---------------------------");
        Iterator  ite= collection.iterator();
        while(ite.hasNext()){  //true就说明集合中有数据,为false,说明集合中没有数据,可以退出循环
           Object obj= ite.next();
            System.out.println(obj);
        }
    }
}
package com.bjsxt.collection;
import com.bjsxt.demo.Gender;
import com.bjsxt.demo.Person;
import java.util.*;
public class Test2 {
    public static void main(String[] args) {
        Collection collection=new LinkedList();//接口new实现类
        System.out.println("集合是否为空:"+collection.isEmpty());
        //(1)添加元素
        collection.add("hello");
        collection.add(new Date());
        collection.add(123);
        collection.add("hello");
        collection.add(new Person("lisli",29, Gender.男));
        System.out.println("集合是否为空:"+collection.isEmpty());
        System.out.println("集合中元素的个数:"+collection.size());
        System.out.println(collection);
        System.out.println(collection.remove("hello")); //将第一个hello删除
        //collection.clear();
        System.out.println(collection);
        System.out.println(collection.contains(123));
        Collection collection1=new LinkedList();
        collection1.add("world1");
        collection1.add("world2");
        collection1.add("world3");
        collection.addAll(collection1);
        System.out.println(collection);
        //遍历集合
        System.out.println("---------------------------------------");
        for(Object obj:collection){
            System.out.println(obj);//默认调用toString()方法
        }
        System.out.println("------------------自己使用迭代器遍历元素 hasNext() ,next()---------------------------");
        Iterator  ite= collection.iterator();
        while(ite.hasNext()){  //true就说明集合中有数据,为false,说明集合中没有数据,可以退出循环
           Object obj= ite.next();
            System.out.println(obj);
        }
    }
}

ArrayList是Object数组元素的封装

当调用ArrayList无参构造方法是创造一个ArrayList的对象。

   private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //初始长度为0,在堆里开空间了
         transient Object[] elementData; //声明一个Object类型的数组,并没有new对象
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //指向 是长度为0的那个数组
     }

第一次调用add方法时,分配给集合的容量时10

 private int size; //集合中元素的个数 ,默认值为0
      private static final int DEFAULT_CAPACITY = 10;
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //调用本类中的方法 
        elementData[size++] = e;
        return true;
    }
        
        private void ensureCapacityInternal(int minCapacity) {//minCapacity 的值为1
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
        
        private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//第一次调用add方法时执行
            return Math.max(DEFAULT_CAPACITY, minCapacity); //return Math.max(10,1);
        }
        return minCapacity;
    }
  private void ensureExplicitCapacity(int minCapacity) { //计算出来的最小容量为10
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0) //10-0>0?true 说明数组的长度已完全不够用
            grow(minCapacity);
    }
        
        private void grow(int minCapacity) {  //10
        // overflow-conscious code
        int oldCapacity = elementData.length;  //oldCapacity= 0
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //0+0 结果为 newCapacity=0
        if (newCapacity - minCapacity < 0)   //0-10<0 true
            newCapacity = minCapacity;          //newCapacity=10;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);   //数组拷贝
    }

当第11次在添加集合元素时,空间容量会变成15,原理如下:

int newCapacity = oldCapacity + (oldCapacity >> 1); 

总结:ArrayList的增删改查都是对底层的Object的类型数组的增删改查,

所以ArrayList的优点时:节省存储空间,按照索引查找效率高

缺点:删除,添加需要大量移动元素时,效率低下,按照内容查找元素,需要逐个判断,效率低下

 

LinkedList底层:

 transient Node<E> first;  //默认值均为null
 transient Node<E> last;
 
  public boolean add(E e) {
        linkLast(e);
        return true;
    }
        
        void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null); //当调用add方法时,new Node创建节点对象
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
        //LinkedList中的私有静态内部类
       private static class Node<E> {
        E item;  //当前要存储的元素
        Node<E> next;  //后继节点
        Node<E> prev;  //前驱节点
        Node(Node<E> prev, E element, Node<E> next) {  //创建一个节点对象
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

Linkedlist的优点:添加,删除元素不需要移动元素,效率高

缺点:每个元素的节点都存储了下一个元素的地址,占据了更多的空间,每个节点的地址不连续,所以按照索引查找也是分别不方便。

 

List接口:

package com.bjsxt.list;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class TestList {
    public static void main(String[] args) {
        List list=new ArrayList();
      // List lits=new LinkedList();
        list.add("hello");
        list.add("world");
        list.add(0,"java");
        list.add(0,123);
       // list.add(7,"sql");java.lang.IndexOutOfBoundsException: Index: 7, Size: 4
        System.out.println(list);
       // list.remove("world");
       // list.remove(123); java.lang.IndexOutOfBoundsException: Index: 123, Size: 3
        //list.remove(new Integer(123));
        System.out.println(list);
        System.out.println("获取元素:"+list.get(0)+"\t"+list.get(1));
        //遍历元素
        System.out.println("--------------普通for循环------");
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        System.out.println("使用扩展出来的listIterator()方法遍历");
        ListIterator listIterator=list.listIterator();
        /*System.out.println("后面有元素吗?"+listIterator.hasNext());
        System.out.println("前面有元素吗?"+listIterator.hasPrevious());
        listIterator.next();//取出一个元素
        System.out.println("后面有元素吗?"+listIterator.hasNext());
        System.out.println("前面有元素吗?"+listIterator.hasPrevious());*/
        System.out.println("正向遍历之前"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
        while(listIterator.hasNext()){
            System.out.println(listIterator.next());
        }
        System.out.println();
        System.out.println("正向遍历之后:"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
        System.out.println("逆向遍历:");
        while(listIterator.hasPrevious()){
            System.out.println(listIterator.previous());
        }
        System.out.println("逆向遍历之后:"+listIterator.hasNext()+"\t"+listIterator.hasPrevious());
    }
}

泛型:是创建集合对象时对集合中存储的元素的数据类型进行限制

泛型符号:<数据类型>

泛型起作用的时间点:javac编译之前。

泛型的分类
(1)泛型接口
 public interface Collection<E>{  //E代表一种数据类型,这个类型什么时候才能知道
}
 //在创建接口的实现类对象时,才能知道,在如下代码中,E所代表的数据类型是Integer
 Collection<Integer> coll=new ArrayList<Integer>();


(2)泛型类
public class ArrayList<E>{  //E的数据类型什么时候知道,创建ArrayList对象时知道

}
  ArrayList<String> al=new ArrayList<String>();

(3)泛型方法
 public boolean add(E e) {}
  //E也代表一种数据类型 ,这个E的数据类型与ArrayList<E> 完全相同的,所以E的类型是在创建ArrayList的对象时确定


可变参数的泛型方法 :
(1)可变参数是JDK1.5
(2)泛型也是JDK1.5
public class Client <T>{ //泛型类
    public void show(T t){ //泛型方法
        System.out.println(t);
    }
    public <Q> void fun(Q q){ //Q的数据类型是在调用该方法时决定
        System.out.println("q="+q);
    }
    public <P>void method(P...p){
         //加强for循环
        for(P i:p){
            System.out.println(i);
        }
    }
}
import java.util.Date;
public class Test {
    public static void main(String[] args) {
        Client<String> client=new Client<String>();//T的类型是String
        client.show("hello");
        //泛型方法,数据类型是在调用该方法时明确的,解决了同一个类中参数个数相同,类型不同的方法重载问题
        client.fun("hello");
        client.fun(123);
        client.fun(new Date());
         //可变参数的泛型方法,解决了数据类型不同,个数不同的方法重载问题
        client.method("hello");
        client.method("world1","world2","world3");
        client.method(123);
        client.method(8.7,9.8,7.6,9.9);
       //可变参数实际上就是一个数组
        Client<Integer> client2=new Client<Integer>();//T的类型时Integer
        client2.show(123);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值