java基础学习16(List)

集合 的体系:
------------| Collection 单例集合的根接口
----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。
-------------------| ArrayList ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。
-------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。
-------------------| Vector 底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。
----------------| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。

List

List接口中特有方法

添加

  • add(int index, E element)
  • addAll(int index, Collection<? extends E> c)

获取:

  • get(int index)
  • indexOf(Object o)
  • lastIndexOf(Object o)
  • subList(int fromIndex, int toIndex)

修改:

  • set(int index, E element)

迭代

  • listIterator()

List接口中特有的方法具备的特点: 操作的方法都存在索引值,只有List接口下面的集合类才具备索引值,其他接口下面的集合类都没有索引值。

class Person{
    private String name;
    private String cardId;

    public Person() {
    }

    public Person(String cardId,String name) {
        this.name = name;
        this.cardId = cardId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    @Override
    public String toString() {
        return "id:"+this.cardId+",name:"+this.name;
    }

    @Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        return p.cardId == this.cardId;
    }
}


public class Test {

    public static void main(String[] args)  {
        Person p1 = new Person("1","张三");
        Person p2 = new Person("2","李四");
        Person p3 = new Person("3","王二");
        Person p4 = new Person("4","麻子");

        List<Person> list1= new ArrayList<>();
        list1.add(p1);
        list1.add(p2);
        list1.add(p3);

        List<Person> list2= new ArrayList<>();
        list2.add(p1);
        //list1.addAll(list2);

        //indexOf与lastIndexOf 与contains一样在比较时也是调用Object的equals
        //System.out.println(list1.indexOf(new Person("1","李四")) );

        //System.out.println(list1.lastIndexOf(new Person("1","李四")) );

        //System.out.println(list1.subList(0,1));

        //list1.set(1,p3);
        //System.out.println(list1);

		Iterator<Person> iterator = list1.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}    

ListIterator特有的方法:

添加:

  • hasPrevious() 判断是否存在上一个元素。
  • hasNext() 判断是否存在下一个元素。
  • previous() 当前指针先向上移动一个单位,然后再取出当前指针指向的元素。
  • next(); 先取出当前指针指向的元素,然后指针向下移动一个单位。
  • add(E e) 把当前有元素插入到当前指针指向的位置上。
  • set(E e) 替换迭代器最后一次返回的元素。

迭代器在变量元素的时候要注意事项: 在迭代器迭代元素 的过程中,不允许使用集合对象改变集合中的元素 个数,如果需要添加或者删除只能使用迭代器的方法进行操作,如果使用过了集合对象改变集合中元素个数那么就会出现ConcurrentModificationException异常。

class Person{
    private String name;
    private String cardId;

    public Person() {
    }

    public Person(String cardId,String name) {
        this.name = name;
        this.cardId = cardId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    @Override
    public String toString() {
        return "id:"+this.cardId+",name:"+this.name;
    }

    @Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        return p.cardId == this.cardId;
    }
}


public class Test {

    public static void main(String[] args)  {
        Person p1 = new Person("1","张三");
        Person p2 = new Person("2","李四");
        Person p3 = new Person("3","王二");
        Person p4 = new Person("4","麻子");

        List<Person> list1= new ArrayList<>();
        list1.add(p1);
        list1.add(p2);
        list1.add(p3);
        list1.add(p4);

        ListIterator<Person> listIterator = list1.listIterator();
        while(listIterator.hasNext()){
            listIterator.next();
        }

        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previous());
        }

    }
 }   
class Person{
    private String name;
    private String cardId;

    public Person() {
    }

    public Person(String cardId,String name) {
        this.name = name;
        this.cardId = cardId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    @Override
    public String toString() {
        return "id:"+this.cardId+",name:"+this.name;
    }

    @Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        return p.cardId == this.cardId;
    }
}


public class Test {

    public static void main(String[] args)  {
        Person p1 = new Person("1","张三");
        Person p2 = new Person("2","李四");
        Person p3 = new Person("3","王二");
        Person p4 = new Person("4","麻子");

        List<Person> list1= new ArrayList<>();
        list1.add(p1);
        list1.add(p2);
        list1.add(p3);
        list1.add(p4);

        ListIterator<Person> listIterator = list1.listIterator();
        while(listIterator.hasNext()){
        	//listIterator.add(new Person("p","p先生"));
            listIterator.next();
            listIterator.set(new Person("p","p先生"));
        }

        System.out.println(list1);
    }
}    

add时返回数据
[id:p,name:p先生, id:1,name:张三, id:p,name:p先生, id:2,name:李四, id:p,name:p先生, id:3,name:王二, id:p,name:p先生, id:4,name:麻子]

set时返回数据
[id:p,name:p先生, id:p,name:p先生, id:p,name:p先生, id:p,name:p先生]

使用三种方式遍历集合的元素.

  • 第一种: 使用get方法遍历。
  • 第二种: 使用迭代器正序遍历。
  • 第三种: 使用foreach遍历。
class Person{
    private String name;
    private String cardId;

    public Person() {
    }

    public Person(String cardId,String name) {
        this.name = name;
        this.cardId = cardId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    @Override
    public String toString() {
        return "id:"+this.cardId+",name:"+this.name;
    }

    @Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        return p.cardId == this.cardId;
    }
}


public class Test {

    public static void main(String[] args)  {
        Person p1 = new Person("1","张三");
        Person p2 = new Person("2","李四");
        Person p3 = new Person("3","王二");
        Person p4 = new Person("4","麻子");

        List<Person> list1= new ArrayList<>();
        list1.add(p1);
        list1.add(p2);
        list1.add(p3);
        list1.add(p4);

        //方式一:使用get方法遍历
        for (int i = 0; i<list1.size();i++){
            System.out.println(list1.get(i));
        }

        System.out.println("====================");

        //方式二:使用迭代器正序遍历
        ListIterator<Person> listIterator = list1.listIterator();
        while(listIterator.hasNext()){
            System.out.println(listIterator.next());
        }
        
        System.out.println("====================");

        //方式三:使用foreach遍历
        for (Person p:list1) {
            System.out.println(p);
        }
    }
}    

ArrayList

ArrayList 特有的方法

  • ensureCapacity(int minCapaci上ty)
  • trimToSize()

ensureCapacity(int n)方法可以对ArrayList低层的数组进行扩容,显示的调用这个函数,如果参数大于低层数组长度的1.5倍,那么这个数组的容量就会被扩容到这个参数值,如果参数小于低层数组长度的1.5倍,那么这个容量就会被扩容到低层数组长度的1.5倍。说这么多,总而言之,记住这个函数可以对低层数组扩容就行了,在适当的时机,好好利用这个函数,将会使我们写出来的程序性能得到提升例如如下两段代码

public class Test {

    public static void main(String[] args)  {
        final int N=1000000;
        Object obj=new Object();
        ArrayList list1=new ArrayList();
        long start=System.currentTimeMillis();
        for(int i=0;i<N;i++){
            list1.add(obj);
        }
        System.out.println(System.currentTimeMillis()-start);

        ArrayList list2=new ArrayList();
        long start2=System.currentTimeMillis();
        list2.ensureCapacity(N);//显示的对低层数组进行扩容
        for(int i=0;i<N;i++){
            list2.add(obj);
        }
        System.out.println(System.currentTimeMillis()-start2);
    }

第2段的效率显然要比第一段高很多,原因是因为,第一段如果没有一次性扩到想要的最大容量的话,它就会在添加元素的过程中,一点一点的进行扩容,要知道对数组扩容是要进行数组拷贝的,这就会浪费大量的时间。如果已经预知容器可能会装多少元素,最好显示的调用ensureCapacity这个方法一次性扩容到位。

ArrayList底层是维护了一个Object数组实现 的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍。

trimToSize方法将底层数组的长度设置为ArrayList实际的容量,动态增长的多余容量被删除了,我们看下到底是怎么回事。

    public static void main(String[] args)  {
        ArrayList al = new ArrayList(10);
        for(int i=0;i<10;i++){
            al.add(i);
        }

        al.add(1);
        al.trimToSize();

        System.out.println(al);
    }

一个初始容量为10的ArrayList,al.add(1);之后,不执行trimToSize时发现debug的内容,发现底层数组的长度是15。
在这里插入图片描述
执行到trimToSize时发现debug的内容,发现底层数组的长度是11。
在这里插入图片描述
也就是说这个方法将elementData的数组设置为ArrayList实际的容量,动态增长的多余容量被删除了。

有小伙伴反应说他debug的时候,并没有看到elementData长度变为15,这里我猜测一下,你用的应该是idea开发工具。这下面我给出一个idea的debug查看方法,也算小科普一下默认情况下Idea对List类型的显示就是这样的,它过于智能了,所以它只把用户关心的东西显示给你看了,让你的焦点放在最重要的数据上。我们只需要做下一面一步操作,就能看到更详细得信息了:
在这里插入图片描述

LinkedList

Linkedlist特有的方法:

方法介绍

  • addFirst(E e)
  • addLast(E e)
  • getFirst()
  • getLast()
  • removeFirst()
  • removeLast()

数据结构

  • 栈 (1.6) : 主要是用于实现堆栈数据结构的存储方式。
    先进后出
    push()
    pop()
  • 队列(双端队列1.5) 主要是为了让我们可以使用LinkedList模拟队列数据结构的存储方式。
    先进先出
    offer()
    poll()

返回逆序的迭代器对象

  • descendingIterator() 返回逆序的迭代器对象
public class Test {

    public static void main(String[] args)  {
        LinkedList list= new LinkedList();
        list.add("张三");
        list.add("李四");
        list.add("王五");
/*
		list.addFirst("狗娃"); //把元素添加到集合的首位置上。
		list.addLast("狗剩");  //把元素添加到集合的末尾处。


		System.out.println("获取集合中首位置的元素:"+list.getFirst());
		System.out.println("获取集合中末尾的元素:"+ list.getLast());

		System.out.println("删除集合中的首位置元素并返回:"+ list.removeFirst());
		System.out.println("删除集合中的末尾素并返回:"+ list.removeLast());


		list.push("狗娃");   //将该元素插入此集合的开头处。
		System.out.println("删除集合的首元素:"+list.pop()); // 移除并返回集合中的第一个元素

		list.offer("狗剩");
		System.out.println("删除集合的首元素: "+list.poll());

		System.out.println("集合中的元素:"+ list);
		*/
        Iterator  it = list.descendingIterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}    

使用LinkedList实现堆栈数据结构的存储方式与队列的数据结构存储方式。

class Team{
    private LinkedList list;
    public Team() {
        this.list = new LinkedList();
    }

    public int size(){
        return list.size();
    }

    public boolean offer(Object o){
        return list.offer(o);
    }

    public Object poll(){
        return list.poll();
    }
}

class Stack{
    private LinkedList list;
    public Stack() {
        this.list = new LinkedList();
    }

    public int size(){
        return list.size();
    }

    public void push(Object o){
         list.push(o);
    }

    public Object pop(){
        return list.pop();
    }
}


public class Test {

    public static void main(String[] args)  {
        Team list = new Team();

        list.offer("张三");
        list.offer("李四");
        list.offer("王二");

        int size = list.size();
        for (int i = 0; i<size;i++){
            System.out.println(list.poll());
        }

    }
 }   

Vector

ArrayLsit与Vector的区别?
相同点: ArrayList与Vector底层都是使用了Object数组实现的。
不同点:

  • ArrayList是线程不同步的,操作效率高,Vector是线程同步的,操作效率低。
  • ArrayList是JDK1.2出现,Vector是jdk1.0的时候出现的。
public class Demo1 {

	public static void main(String[] args) {
		Vector v  =  new Vector();
		//添加元素
		v.addElement("张三");
		v.addElement("李四");
		v.addElement("王五");
		//迭代该集合
		Enumeration e = v.elements(); //获取迭代器
		while(e.hasMoreElements()){
			System.out.println(e.nextElement());
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值