黑马程序员_JAVA笔记14——集合框架(List、HashSet、TreeSet)

本文详细介绍了Java集合框架的基本概念,包括数组与集合的区别、各种集合类的特点及应用场景,如ArrayList、LinkedList、HashSet、TreeSet等,并提供了丰富的示例代码。
-------  android培训java培训、期待与您交流! ----------
1、为什么出现集合类,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最长哟昂的一种方式。
        数组与集合类都是容器,有何不同?数组虽然也可以存储对象,但长度是固定的,集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。数组只能存储同一种数据类型。
        集合类的特点:集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象
2、容器
        collection接口:
                List:
                        ArrayList:底层数据结构使用的是数组结构。特点:查询速度快但增删很慢。
                                        线程不同步。数组默认长度10,当元素数超过10,就new一个新
                                        的数组,长度增长50%。将元素copy过来然后加上新元素
                        LinkedList:底层使用的是链表数据结构。特点:查询慢增删快
                        Vector:底层是数组数据结构(Vector是1.0,集合框架是1.2出现的),功能
                                        与ArrayList相同。但是线程同步。低效。数组默认长度10,当元
                                        素数超过10,就new一个新的数组,长度增长100%。将元素
                                        copy过来然后加上新元素

                Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
                        Set集合功能与Collection功能一致
                        HashSet:底层数据结构是哈希表
                        TreeSet:
为什么出现这么多容器:因为每一个容器对数据的存储方式不同,这个存储方式称为:数据结构
3、示例:
/*
    add方法的参数类型时Object,以便于接收任意类型对象。
    集合中存储的都是对象的引用或地址。

Iterator的设计原理:
    把集合中取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。
    那么取出方式就被定义成了内部类。
    而每一个容器的数据结构不同。
    所以取出的动作细节也不一样,但是都有共性内容:判断和取出,那么可以将其共性抽取。
    那么这些内部类都复合一个规则,该规则是Iterator接口。
    如何获取集合的取出对象,通过一个对外提供的方法iterator();

*/
import java.util.*;
class CollectionDemo
{
        public static void main(String[] args)
        {
                //创建一个集合容器,使用Collection解扣子的子类,ArrayList
                ArrayList al = new ArrayList();
                al.add("java1");        
                al.add("java2");   
                al.add("java3"); 
                al.add("java4");   

                ArrayList al2 = new ArrayList();
                al2.add("java2");        
                al2.add("java3");   
                al2.add("java6"); 
                al2.add("java7");   
                
                //
                Iterator it = al.iterator();//获取迭代器,用于去除集合中的元素。
                sop(it.next());//取出集合中下一个元素
                while(it.hasNext())//判断下面是否还有元素,返回boolean
                {
                        it.next();
                }
                for(Iterator it = al.iterator();it.hasNext();)
                {
                        sop(it.next());
                }
                //取交集
                al.retainAll(al2)//al中只会保留和al2中相同的元素,al与al2的交集
                
                //去交集
                al.removeAll(al2);//al中保留al2中所没有的元素,即去掉al中二者的交集,但是al2不变
                //获取个数
                sop("size:"+al.size());
                
                //打印集合中的对象
                sop(al);//会依次打印出集合中所有的对象
                
                //删除元素
                al.remove("java3");//删除集合中的java3元素
                al.clear();//删除集合中所有元素,清空集合。
                
                //判断元素
                sop(al.contains("java2");//al中是否包含java2,返回boolean
                sop(al.isEmpty());//al是否为空,返回boolean
        }
        public static void sop(Object obj)
        {
                System.out.println(obj):
        }
}

4、List集合共性方法:
/*
Collection
        List:元素师有序的,元素可以重复,因为该集合体系有索引。
        Set:元素是无序的,元素不可以重复。
List:
        特有方法:凡是可以操作角标的方法都是该体系特有方法
增:
        add(index,element);
        addAll(index,Collection);
删:
        remove(index);
改:
        set(index,element)
查:
        get(index);
        subList(from,to)
        listIterator();

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

imort 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(1,"java09");
                //删除指定位置元素
                al.remove(2);
                //修改指定位置元素
                al.set(2,"java998");
                //获取角标处元素
                sop(al.get(1));
                //获取所有元素
                for(Iterator it = al.iterator();it.hasNext();)
                {
                        sop(it.next());
                }

                //通过indexOf获取对象的位置
                sop(al.indexOf("java02");
                List sub = al.subList(1,3);//取子列表,包含1不包含3

                //演示列表迭代器
                //在迭代过程中,准备添加或者删除元素。用Iterator;
                Iterator it = al.iterator();
                while(it.hasNext())
                {
                        Object obj = it.next();
                        if(obj.equals("java02")
                                it.add("jfava333");//出现并发异常
                                it.remove();//删除集合中对象的引用
                        sop(obj)
                }

                //用ListITerator,因为List有索引,所以能进行增删改查
                ListIterator li = al.ListIterator();
                while(li.haiNext())//判断集合中下一个元素是否存在:正向遍历
                {
                        Object obj = li.next();
                        if (obj.equals("java01"))
                                li.set("java003");
                                li.add("java3333");
                }
                while(li.haiPrevious())//判断集合中前一个元素是否存在,逆向遍历
                {
                        Object obj = li.previous();
                        if (obj.equals("java01")
                                li.set("java003");
                                li.add("java3333");
                }
                
        }
        public static void sop(Object obj)
        {
                 System.out.println(obj);
        }
        
}

Vector示例:
/*
枚举就是Vector特有的取出方式
发现枚举和迭代很像
其实枚举和迭代是一样的
因为枚举的名称以及方法的名称都过长
所以被迭代器取代了
枚举就用的少了
*/
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());
                }
        }
}

5、linkedList
/*
特有方法:
addFirst();
addLast();
getFirst();
getLast();只取不删
removeFirst();取并删
removeLast();
注意当linkedList 为空时,进行上述操作,抛出异常NoSuchElementsException

1.6版本后:出现替代方法
offerFirst();//添加元素
offerLast();
peekFirst();//获取元素,但不删除,如果集合没有元素,返回null,不抛异常
peekLast();
pollFirst();//获取元素,并在链表中删除,如果集合中没有元素,返回null,而不是抛异常
pollLast();
*/
import java.util.*;
class LinkedListDemo
{
        public static void main(String[] args)
        {
                LinkedList link = new LinkedList();
                link.addFirst("java01");
                link.addFirst("java02"); 
                link.addFirst("java03"); 
                sop(link);//结果java03  java02   java01

                LinkedList link1 = new LinkedList();
                link.addLast("java01");
                link.addLast("java02"); 
                link.addLast("java03"); 
                sop(link1);//结果java01 java02  java03
                sop(link1.getFirst());//java01
                sop(link1getLast());//java03
                sop(link1.removeFirst());//先获取第一个,然后删除
                sop(link1.size());

                //删除所有元素
                while(!link1.isEmpty())
                {
                        sop(link.removeFirst());
                }
        }
        public static void sop(Object obj)
        {
                System.out.println(obj);
        }
}

堆栈:先进后出,如同一个杯子
队列:先进先出,First in First out      FIFO如同一个水管

import java.util.*;
class DuiLie
{
        private LinkedList link;
        DuiLie()
        {
                link = new LinkedList;
        }
        public void myAdd(Object obj)
        {
                link.addFirst(obj);
                //ling.addLast(obj);
        }
        public Object myGet()
        {    
                return link.removeLast();
                //return link.removeFirst();
        }
        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");

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


去除ArrayList中的重复元素
class ArrayListDemo
{
        public static void main(String[] args)
        {
                ArrayList al = new ArrayList();
                al.add("java01");
                al.add("java02");
                al.add("java03");
                al.add("java04");
                al.add("java05");
                al.add("java06");
                System.out.println(singleElement(al));

                //在迭代时,循环中的next()调用一次,就要hasNext判断一次。不要hasNext一次而next多次,否则易出NoSuchElementException
                Iterater it = al.Iterator();
                while(it.hasNext())
                {
                        sop(it.next()+"       "+it.next());
                        //输出:java01....java02      java03......java04       java05......java06
                        //但是当没有al.add("java06")时,最后一次循环的it.next()取不到值,
                        //出异常
                }
        }
        public static ArrayList singleElement(ArrayList al)
        {
                /*
                原理:创建新容器,判断该容器中是否含有al中的元素,若没有则添加。(这样,不重复的元素会添加进去,而重复的元素只会添加进一次,等再次添加时新容器中已有该元素,判断为false,因此不添加,这样新容器中就是去除了重复元素的集合,将该新容器返回即可)

                */
                ArrayList all = new ArrayList();
                Iterator it = al.iterator();
                while(it.haiNext())
                {
                        Object obj = it.next();
                        if(!all.contains(obj))
                                all.add(obj);
                }
        }
}

List集合判断元素是否相同,依靠的是equals方法。contains      remove

6、频繁增删:linkedList
     涉及增删,但不频繁:linkedList   或ArrayList
    涉及增删,涉及查询:ArrayList

7、     Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
                        Set集合功能与Collection功能一致
                        HashSet:底层数据结构是哈希表

HashSet是如何保证元素的唯一性?是通过元素的两个方法,hashCode()和equals()来完成。如果元素的HashCode值相同,才会判断equals是否为true,如果元素的哈希值不同,不会调用equals。另外:若两个元素的值不同,地址值相同,过程是这样的:先比较地址值,发现相同,然后比较equals,发现值不同,则,在哈希表中,该地址值下回存入两个不同的对象,即一个地址两个对象,在打印时,可打印出这两个对象。

HashSet数据结构式哈希表,线程是非同步的。保证元素唯一性的原理,判断元素的hashCode是否相同,如果相同,还会继续判断元素的equals方法,是否为true

注意:对于判断元素是否存在以及删除等操作,都依赖于元素的hashcode和equals方法
class Demo
{
        /*
        public int hashCode()
        {
                return 60;//返回值3c, 十六进制形式
        }
        */
}
class HashSetDemo
{
        public static void sop(Object obj)
        {
                System.out.println(obj);
        }
        public static void main(String[] args)
        {
                Demo d = new Demo();
                Demo d1 = new Demo();
                sop(d);//因为重写了hashCode(),所以打印的d和d1的地址值是一样的
                sop(d1);//这是因为,d.toString()时,调用hashCode(),返回d的哈希值
                            //但是我们重写后,返回的是3c,因此d  和d1打印地址值相同

                HashSet  hs = new HashSet();
                hs.add("java01");
                hs.add("java02");
                hs.add("java03");
                hs.add("java04");
                hs.add("java03");
                hs.add("java04");

                sop(hs.add("java"));//add方法返回值为boolean的,此时打印true,能存
                sop(hs.add("java"));//应为hs中已经存在java,不能继续存入,打印false
                Iterator it = hs.iterator();
                while(it.hasNext())//打印后只1234,因为HashSet中元素不重复
                        sop(it.next())
        }
}

8、TreeSet:
                可以对Set集合中的元素进行排序
                底层数据结构式二叉树
                调用的是compareTo()方法。
                保证元素 唯一性的依据: 调用的是compareTo()方法,返回值为0

    排序的第一种方式:让元素自身具备比较性,元素实现compareable接口,覆盖compareTo()方法。这种方式也称为元素的自然顺序,或默认顺序。

        
class TreeSetDemo
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet();    
                ts.add("fd");
                ts.add("cdf");
                ts.add("Dd");
                ts.add("b");
                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        System.out.println(it.next());
                        //结果:     Dd     b         cdf       fd 
                        //按首字母值排序,升序
                }


        }
}

/*
向TreeSet中存储自定义对象:重写compareTo方法,按我们自定义的方式返回值,先比较主要元素,若主要元素相同就比较次要元素。
*/
class TreeSetDemo
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet();    
                ts.add(new Student("zhangsan",19);
                ts.add(new Student("lisi",30);
                ts.add(new Student("wangwu",19);
                ts.add(new Student("zhangsan",13);

                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        System.out.println(it.next());
                     
                }
        }
}
class Student implements Comparable
{
        private String name;
        private int age;
        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public int compareTo(Object obj)
        {
                /*此时按升序排列
                if(!(obj instanceof Student))
                        throw new RunTimeException("不是学生");
                Student s = (Student)obj;
                if(this.age>s.age)
                        return 1;
                if(this.age==s.age)
                         return (this.name).compareTo(s.name);//String类本身就实现了Compareable接口,有compareTo方法
                return -1;*/

                //如果这样,那么元素是按存入的顺序排列的,存入元素时,会自动调用compareTo,返回1表示大于,返回0表示等于(此时不存入),返回-1表示小于。在这里全返回1表示后存入的对象比前一个对象大。
                return  1;
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                retrun age;
        }
}


排序的第二种方式:当元素自身不具备比较性,或具备的比较性不是所需要的。这时需要让集合自身具备比较性。在集合一初始化时,就有了比较方式。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数

当两种排序都存在时,以比较器为主

定义一个类,实现Comparator接口,覆盖compare方法。
class Student implements Comparable
{
        private String name;
        private int age;
        Student(String name,int age)
        {
                this.name = name;
                this.age = age;
        }
        public int compareTo(Object obj)
        {
               此时按升序排列
                if(!(obj instanceof Student))
                        throw new RunTimeException("不是学生");
                Student s = (Student)obj;
                if(this.age>s.age)
                        return 1;
                if(this.age==s.age)
                         return (this.name).compareTo(s.name);//String类本身就实现了Compareable接口,有compareTo方法
                return -1;

              
        }
        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                retrun age;
        }
}
class TreeSetDemo
{
        public static void main(String[] args)
        {
                TreeSet ts = new TreeSet (new MyCompare());     //表示使用指定比较器
                ts.add(new Student("zhangsan",19);
                ts.add(new Student("lisi",30);
                ts.add(new Student("wangwu",19);
                ts.add(new Student("zhangsan",13);

                Iterator it = ts.iterator();
                while(it.hasNext())
                {
                        System.out.println(it.next());
                        //结果:     Dd     b         cdf       fd 
                        //按首字母值排序,升序
                }
        }
}
class MyCompare implements Comparator//自定义比较器
{
        public int compare(Object c1,Object c2)
        {
                Student s1 = (Student)o1;
                Student s2 = (Student)o2;
                int  num = s1.getName().compareTo(s2.getName());
                if(num==0)//当name相同时,比较age
                {
                        return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge());
                }
                return num;
        }
}

比较器调用过程: 就是让集合具备比较的功能,使用集合构造函数方法
创建TreeSet集合对象,此时:
         TreeSet ts = new TreeSet(new MyCompare()); 表示使用自定义比较器
       
创建类实现接口Comparator,覆盖接口的compare方法
        class MyCompare implements Comparator//自定义比较器
        {
        public int compare(Object c1,Object c2)
        {
自定义比较的方式,最后的返回值
return 正数或负数或0;一般就是1  -1  0
}
}
向TreeSet对象中添加元素,此时元素就自动的,按自定义的比较器在集合内排序存放

compareTo调用过程理解: 让集合元素具备比较性
创建TreeSet集合对象,此时:
           TreeSet ts = new TreeSet(); 表示使用compareTo()方法
创建类实现Comparable接口,覆盖compare方法。并且此类生成的对象,是准备向集合中添加的元素。 在覆盖后的compare方法中对该类的成员如name  age等进行比较,返回值1 -1 或0
向集合中添加元素,集合就会自动调用compare方法,按覆盖后的compare方法进行排序存放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值