Java基础-14-集合

Java基础-集合

集合入门

1、集合框架(体系概述)

集合类Collection:

  • 为什么出现集合类?面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象进行操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

  • 数组和集合类同是容器,有何不同?

    数组虽然也可以存储对象,但长度是固定的;集合长度是可以变得,数组中可以存储基本数据类型,集合只能存储对象。
    
  • 集合类的特点。

    集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
    
  • 为什么会出现这么多的容器呢?

    因为每一个容器对数据的存储方式都有不同,这个存储方式称之为:数据结构。
    

集合图:

Collection类属于java.util.*;包中

2、集合框架(共性方法)

import java.util.*;
class CollectionDemo
{
    public static void main(String[]args)
    {
        method_1();
        method_2();
    }
    public static void method_1()
    {
        //创建一个集合容器,使用Collection接口的子类ArrayList类
                ArrayList al = new ArrayList();

                //添加元素到容器al中。
                al.add("java01");
                al.add("java02");
                al.add("java03");
                al.add("java04");

                //打印容器中的元素
                System.out.println("al中有:"+al);

                //获取个数,集合长度。
                System.out.println("al.size :"+al.size());

                //删除元素
                al.remove(1);
                System.out.println("删除java03是否成功?"+al.remove("java03"));

                //清空集合
                al.clear();
                System.out.println("清空集合后al中有:"+al);

                //判断元素
                System.out.println("al中是否存在java03?"+al.contains("java03"));
                System.out.println("al是否为空?"+al.isEmpty());
    }
    public static void method_2()
    {
        ArrayList al1 = new ArrayList();
        ArrayList al2 = new ArrayList();
        al2.add("java01");
        al2.add("java02");
        al2.add("java03");
        al2.add("java04");
        al1.add("java01");
        al1.add("java02");
        al1.add("java05");
        al1.add("java06");

        //取交集
        al1.retainAll(al2);
        System.out.println("al1取了al2的交集后的结果是"+al1);

        //去掉相同的子集
        al2.removeAll(al1);
        System.out.println("al2被去掉了al1中相同的子集后的结果是:"+al2);

    }
}

输出结果:

al中有:[java01, java02, java03, java04]
al.size :4
删除java03是否成功?true
清空集合后al中有:[]
al中是否存在java03?false
al是否为空?true
al1取了al2的交集后的结果是[java01, java02]
al2被去掉了al1中相同的子集后的结果是:[java03, java04]

图:

3、集合框架(迭代器)

  • 什么是迭代器?

    其实就是集合取出元素方式。就把取出方式定义在集合内部,这样取出方式就可以直接访问集合内容的元素,那么取出方式就被定义成内部类,而每一个容器的数据结构不同,所以取出的动作细节不一样,但是都有共性内容:判断和取出,那么可以将共性抽取,那么这些内部类都符合一个规则,该规则就是Iterator。
    
  • 如何获取集合的取出对象呢?

    通过一个对外提供的方式:iterator();
    

import java.util.*;
class CollectionDemo
{
    public static void main(String[]args)
    {
        method_get();
    }
    public static void method_get()
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        Iterator it = al.iterator();
        while(it.hasNext())
        {
            System.out.println(it.next());
        }

        //另一种使用迭代器的方法,可以更省资源
        System.out.println();
        for(Iterator it1 = al.iterator();it1.hasNext();)//当for循环完毕,Iterator it1 = al.iterator()语句释放
        {

            System.out.println(it1.next());
        }
    }
}

输出结果:

java01
java02
java03
java04

java01
java02
java03
java04

4、集合框架(List集合共性方法)

Collection

|--List:元素是有序的,同时元素可以重复,因为该集合体系有索引

|--Set:元素是无序的,不能重复。

List(接口):特有方法:凡是可以操作角标的方法都是该体系特有方法。

  • 增:

    void add(int index,E element);//将指定的元素插入此列表中的指定位置。
    boolean addAll(int index,Collection c);// 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
    
  • E remove(int index);// 移除此列表中指定位置上的元素。
    
  • E set(int index, E element);//用指定的元素替代此列表中指定位置上的元素。
    
  • E get(int index);//返回此列表中指定位置上的元素。
    List<E> subList(int fromIndex , int toIndex);//返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
    ListIterator<E> listIterator();//返回此列表元素的列表迭代器(按适当顺序)。
    

演示代码:

import java.util.*;
class ListDemo
{
    public static void main(String[]args)
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        System.out.println("原集合al:"+al);

        //在指定的位置添加元素:
        al.add(1,"java09");
        System.out.println("al.add(1,\"java09\"):"+al);

        //删除指定位置元素
        al.remove(2);
        System.out.println("al.remove(2):"+al);

        //修改元素
        al.set(1,"java0001");
        System.out.println("al.set(1,\"java0001\"):"+al);

        //通过角标获取元素
        System.out.println("al.get(1):"+al.get(1));

        //获取所有元素
        //方式1
        for(int x = 0;x<al.size();x++)
        {
            System.out.println(al.get(x));
        }

        //方式2
        System.out.println();
        Iterator it = al.iterator();
        while(it.hasNext())
        {
            System.out.println(it.next());
        }
    }
}

输出结果:

原集合al:[java01, java02, java03, java04]
al.add(1,"java09"):[java01, java09, java02, java03, java04]
al.remove(2):[java01, java09, java03, java04]
al.set(1,"java0001"):[java01, java0001, java03, java04]
al.get(1):java0001
java01
java0001
java03
java04

java01
java0001
java03
java04

5、集合框架(ListIterator)

演示代码:

import java.util.*;
class ListDemo
{
    public static void main(String[]args)
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        System.out.println("原集合al:"+al);

        //通过indexOf获取对象的位置
        System.out.println("java02的index是:"+al.indexOf("java02"));

        //获取子对象集
        List sub = al.subList(1,3);
        System.out.println("下标1到2的子对象集是:"+sub);

    }
}

输出结果:

原集合al:[java01, java02, java03, java04]
java02的index是:1
下标1到2的子对象集是:[java02, java03]

演示代码:下面这段代码会引起异常,原因是并发操作。

import java.util.*;
class ListDemo
{
    public static void main(String[]args)
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        System.out.println("原集合al:"+al);

        Iterator it = al.iterator();
        //下面代码目的是在迭代过程中,使用集合的方法来对it对象中的元素进行添加或删除元素。
        while(it.hasNext())
        {
            Object obj = it.next();
            if(obj.equals("java02"))
            {
                al.add("java09");//这是集合的方法,会引起并发异常
            }
            System.out.println("obj"+obj);
        }
    }
}

输出结果:

原集合al:[java01, java02, java03, java04]
objjava01
objjava02
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886)
    at java.util.ArrayList$Itr.next(ArrayList.java:836)
    at day09.ListDemo.main(Outer.java:18)
  • 以上代码引发了问题,就是如何在迭代器中进行元素的添加或删除呢?

    List集合特有的迭代器,ListIterator是Iterator的子接口。在使用Iterator中的迭代器迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。所以,在迭代,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断、取出和删除的操作。如果想要其他的操作如:添加、修改等,就需要使用其子接口:ListIterator,该接口只能通过ListIterator方法获取
    

改进代码如下:

import java.util.*;
class ListDemo
{
    public static void main(String[]args)
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add("java04");
        System.out.println("原集合al:"+al);

        ListIterator li = al.listIterator();
        while(li.hasNext())
        {
            Object obj = li.next();
            //添加
            if(obj.equals("java02"))
            {
                li.add("java09");
            }

            //修改
            if(obj.equals("java03"))
            {
                li.set("java003");
            }

        }
        System.out.println("修改后al:"+al);
    }
}

输出结果:

原集合al:[java01, java02, java03, java04]
修改后al:[java01, java02, java09, java003, java04]

6、集合框架(List集合具体对象的特点)

List

|--ArrayList:底层的数据结构使用的是数组结构,特点:查询快,但增删稍慢,线程不同步。

|--LinkedList:底层使用链表数据结构,增删速度快,查询慢。

|--Vector:底层是数组数据结构,被ArrayList替代了,但它们间不同的是Vector线程同步。

7、集合框架(Vector中的枚举)

import java.util.*;
class VectorDemo
{
    public static void main(String[]args)
    {
        Vector v = new Vector();
        v.add("java01");
        v.add("java02");
        v.add("java03");
        v.add("java04");
        Enumeration en = v.elements();
        while(en.hasMoreElements())
        {
            System.out.println(en.nextElement());
        }
    }
}

输出结果:

java01
java02
java03
java04
  • 枚举就是Vector特有的取出方式。

    发现枚举和迭代器很像,其实枚举和迭代是一样的,因为枚举的名称以及方法的名称都过长,所以被迭代器取代了,枚举就很少被人使用了。
    

8、集合框架(LinkedList)

LinkedList特有方法:

void addFirst(E e);//将指定元素插入此列表的开头。
void addLast(E e);// 将指定元素添加到此列表的结尾。
boolean offerFirst(E e );//在此列表的开头插入指定的元素。JDK1.6版本
boolean offerLast(E e);//在此列表末尾插入指定的元素。JDK1.6版本

E getFirst();//返回此列表的第一个元素。
E getLast();// 返回此列表的最后一个元素。
E peekFirst();//获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。JDK1.6版本
E peekLast();//获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。JDK1.6版本

E removeFirst();//移除并返回此列表的第一个元素。
E removeLast();//移除并返回此列表的最后一个元素。
E pollFirst();//获取并移除此列表的第一个元素;如果此列表为空,则返回 null。JDK1.6版本
E pollLast();//获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。JDK1.6版本

因为如果集合中没有元素,会出现NoSuchElementException,在JDK1.6出现了替代方法,以上JDK1.6版本的功能,这些方法不会返回异常而是null。

9、集合框架(LinkedList练习)

使用LinkedList模拟一个堆栈或者队列数据结构。 堆栈:先进后出,如同一个杯子。 队列:先进先出,如同一个水管。 测试代码:

import java.util.*;
class DuiLie
{
    private LinkedList link;
    DuiLie()
    {
        link = new LinkedList();
    }
    public void bianli()
    {
        for(int x = 0;x<link.size();x++)
        {
            System.out.print(link.get(x)+" ");
        }
        System.out.println();
    }
    public void myAdd(Object obj)
    {
        link.addFirst(obj);
    }
    public Object myGet()
    {
        return link.removeLast();
    }
    public boolean isNull()
    {
        return link.isEmpty();
    }
}
class LinkedListTest
{
    public static void main(String []args)
    {
        DuiLie dl = new DuiLie();
        dl.myAdd("java01");
        dl.myAdd("java02");
        dl.myAdd("java03");
        dl.myAdd("java04");

        dl.bianli();//遍历

        while(!dl.isNull())
        {
            System.out.println(dl.myGet());
        }
    }
}

输出结果:

java04 java03 java02 java01 
java01
java02
java03
java04

10、集合框架(ArrayList练习)

去除ArrayList集合中的重复元素

import java.util.*;
class ArrayListTest
{
    public static ArrayList SingleElement(ArrayList al)
    {
        //定义一个临时容器
        ArrayList newAl = new ArrayList();

        Iterator it = al.iterator();
        while(it.hasNext())
        {
            Object obj = it.next();
            if(!newAl.contains(obj))
            {
                newAl.add(obj);
            }
        }
        return newAl;
    }
    public static void main(String[]args)
    {
        ArrayList al = new ArrayList();
        al.add("java01");
        al.add("java01");
        al.add("java02");
        al.add("java04");
        al.add("java06");
        al.add("java01");

        System.out.println("原al:"+al);
        System.out.println("新al:"+SingleElement(al));
    }
}

输出结果:

原al:[java01, java01, java02, java04, java06, java01]
新al:[java01, java02, java04, java06]

11、集合框架(ArrayList练习)

将自定义对象作为元素存储到ArrayList集合中,并去除重复元素。 比如:存人对象:同姓名同年龄,视为同一个人,为重复元素。 思路: 1、对人描述 2、定义容器,将人存入。 3、取出。

代码:

import java.util.*;
class Person
{
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    public String getName()
    {
        return name ;
    }
    public int getAge()
    {
        return age;
    }
    public boolean equals(Object obj)//List集合判断元素是否相同,依据是元素(对象)的equals方法
    {
        if(!(obj instanceof Person))
        {
            return false;
        }
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
}

class ArrayListTest2
{
    public static ArrayList SingleElement(ArrayList al)
    {
        //定义一个容器
        ArrayList newAl = new ArrayList();
        Iterator it = al.iterator();
        while(it.hasNext())
        {
            Object obj = it.next();
            if(!(newAl.contains(obj)))//即调用了Person类中的自定义equals函数
            {
                newAl.add(obj);
            }
        }
        return newAl;
    }
    public static void main(String []args)
    {
        ArrayList al = new ArrayList();
        al.add(new Person("lisi01",30));
        al.add(new Person("lisi02",33));
        al.add(new Person("lisi03",22));
        al.add(new Person("lisi04",30));
        al.add(new Person("lisi01",30));

        al = SingleElement(al);
        Iterator it = al.iterator();
        while(it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"::"+p.getAge());
        }
    }
}

输出结果:

lisi01::30
lisi02::33
lisi03::22
lisi04::30

12、集合框架(HashSet)

Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。 Set

|---HashSet:底层数据结构是哈希表

|---TreeSet

Set集合的功能和Collection是一致的。

测试代码:

import java.util.*;
class HashSetDemo
{
    public static void main(String []args)
    {
        HashSet hs = new HashSet();
        hs.add("java01");
        hs.add("java02");
        hs.add("java03");
        hs.add("java04");
        Iterator it = hs.iterator();
        while(it.hasNext())
        {
            System.out.println(it.next());
        }//无序存,按哈希表顺序存。

    }
}

输出结果:

java04
java03
java02
java01

13、集合框架(HashSet存储自定义对象)

往HashSet集合中存入自定义对象,姓名和年龄相同为同一个人,重复元素。

import java.util.*;
class HashSetTest
{
    public static void main(String []args)
    {
        HashSet hs = new HashSet();
        hs.add(new Person("al",11));
        hs.add(new Person("a2",12));
        hs.add(new Person("a3",13));
        hs.add(new Person("a2",12));

        Iterator it = hs.iterator();
        while(it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"::"+p.getAge());
        }

    }
}
class Person
{
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    public String getName()
    {
        return name ;
    }
    public int getAge()
    {
        return age;
    }
    public boolean equals(Object obj)//List集合判断元素是否相同,依据是元素(对象)的equals方法
    {
        System.out.println("equals() run");
        if(!(obj instanceof Person))
        {
            return false;
        }
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    public int hashCode()
    {
        System.out.println("hashCode() run");
        //字符串类型的变量可以调用字符串自己的哈希值函数,返回字符串自己独有的哈希值
        return this.name.hashCode()+this.age*37; //为了保证哈希值唯一而在对象内容不一样的情况下不用去调用equals方法
    }
}

输出结果:

hashCode() run
hashCode() run
hashCode() run
hashCode() run
equals() run
al::11
a3::13
a2::12

HashSet是如何保证元素唯一性的呢?

是通过元素(对象)的两个方法:hashCode和equals来完成,如果元素的hashCode值相同,才会判断equals是否为true,如果元素的hashCode值不同,不会调用equals。

14、集合框架(HashSet判断和删除的依据)

import java.util.*;
class HashSetTest
{
    public static void main(String []args)
    {
        HashSet hs = new HashSet();
        Person p1 = new Person("a2",12);
        hs.add(new Person("al",11));
        hs.add(p1);
        hs.add(new Person("a3",13));
        System.out.println("....");
        //hs.add(new Person("a2",12));

        System.out.println("测试判断是否包含的功能:"+hs.contains(new Person("a2",12)));

        hs.remove(p1);
        /*
        Iterator it = hs.iterator();
        while(it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"::"+p.getAge());
        }
        */
    }
}
class Person
{
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    public String getName()
    {
        return name ;
    }
    public int getAge()
    {
        return age;
    }
    public boolean equals(Object obj)//List集合判断元素是否相同,依据是元素(对象)的equals方法
    {
        System.out.println("equals() run");
        if(!(obj instanceof Person))
        {
            return false;
        }
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    public int hashCode()
    {
        System.out.println("hashCode() run");
        //字符串类型的变量可以调用字符串自己的哈希值函数,返回字符串自己独有的哈希值
        return this.name.hashCode()+this.age*37; //为了保证哈希值唯一而在对象内容不一样的情况下不用去调用equals方法
    }
}

输出结果:

hashCode() run
hashCode() run
hashCode() run
....
hashCode() run
equals() run
测试判断是否包含的功能:true
hashCode() run

对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值