黑马程序员——java基础——集合(一)

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

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

集合的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象

List集合和Set集合
List 集合元素是有序的,可以重复,因为该集合有索引
ArrayList 底层结构是数组结构,特点查询快,增删较慢,线程不同步
LinkedList 底层结构是链表结构,特点 增删快,查询较慢
Vector 底层结构是数组结构,它是线程同步的,被ArrayList替代了

Set集合 元素是无序的,不可以重复
HashSet 底层结构是哈希表
其保证元素唯一性的原理:
在存入时首先是比较各元素的哈希值,若哈希值相同再调用equals方法,在添加元素时,会调用元素的hashCode方法和equals方法
注意:HashSet集合中删除,判断元素是否存在等方法依赖的方法是hashCode和equals方法
元素在HashSet集合中是没有顺序的,或者说是按照其特定的哈希值排序
TreeSet 底层结构是二叉树
TreeSet集合可以对集合中的元素进行排序
TreeSet集合在添加一个对象时,对象必须具备比较性
TreeSet集合保证元素唯一性的原理:在添加时他会调用所添加元素的compareTo方法
通过返回的值对元素进行排序,若返回0,则认为这两个元素是一样的
该集合对元素进行排序的另一种方法是:自定义一个比较器,并将这个比较器作为参数传给该集合的构造函数,实现comparator接口,复写该接口中的compare方法

集合中的较为常用的共性方法:
boolean add(E e) 
确保此 collection 包含指定的元素(可选操作)。 
boolean addAll(Collection<? extends E> c) 
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。 
void clear() 
移除此 collection 中的所有元素(可选操作)。 
boolean contains(Object o) 
如果此 collection 包含指定的元素,则返回 trueboolean containsAll(Collection<?> c) 
如果此 collection 包含指定 collection 中的所有元素,则返回 trueboolean equals(Object o) 
比较此 collection 与指定对象是否相等。 
int hashCode() 
返回此 collection 的哈希码值。 
boolean isEmpty() 
如果此 collection 不包含元素,则返回 true。 
Iterator<E> iterator() 
返回在此 collection 的元素上进行迭代的迭代器。 
boolean remove(Object o) 
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 
boolean removeAll(Collection<?> c) 
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。 
boolean retainAll(Collection<?> c) 
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 
int size() 
返回此 collection 中的元素数。 
Object[] toArray() 
返回包含此 collection 中所有元素的数组。        

对于不同的集合它还具有一些自己特定的方法,如List集合可以通过角标对元素进行操作等,对于一些特定的方法,我们可以通过查阅API文档来学习。

迭代器是集合中取出元素的一种非常重要的方法

List集合:取出集合中的元素

import java.util.*;
class ListDemo
{
    public static void main(String[] args) 
    {
        ArrayList a = new ArrayList();
        a.add("a");
        a.add("b");
        a.add("c");
        a.add("d");

        System.out.println(a);
        /*
        在取出集合中的元素时,在取出的过程中对集合中的元素进行操作
        注意:在使用迭代器的方法取出集合中的元素时,
        不能使用集合中的方法在取出的过程中对元素进行操作,
        否则会发生 ConcurrentModificationException,并发修改异常

        list 集合有其特殊的迭代器方法ListIterator,可以在取出的过程中对元素进行操作
        因为该集合每个元素有对应的角标
        */  
        ListIterator li = a.listIterator();
        while(li.hasNext())
        {
            Object obj = li.next();
            if (obj.equals("b"))
            {
                li.set("f");
            }
            System.out.println(obj);//obj不会随着对元素的不同操作而改变,它在元素改变之前就已经指向了该元素
        }
        System.out.println(a);

        //逆向遍历集合并取出集合中的元素,这是List集合才具备的方法
        while (li.hasPrevious())
        {
            System.out.println(li.previous());
        }
    }
}

总结:迭代器是取出集合中元素常用的方法,在取出元素的过程中一般不能对元素进行操作,但对于List集合而言,由于其具有角标的特性,所以在元素的取出过程中,它具备一些特定的对元素进行操作的方法。

用LinkedList模拟队列和堆栈数据结构
队列:先进先出
堆栈:先进后出
思路:
自定义一个类(基于LinkedList),对外提供添加和取出的方法

import java.util.*;
class DuiLie
{
    private LinkedList link ;//将link定义在成员位置上,这样每个方法就可以使用这个对象
    DuiLie()
    {
        link = new LinkedList();
    }
    public void Myadd(Object obj)
    {
        link.addLast(obj);
    }
    public Object Myget()
    {
        //因为获取元素后,那个元素就需要清除,所以这里用remove() 而不用get()
        return link.removeFirst();
    }
    public boolean isNull()
    {
        return link.isEmpty();
    }
}

class LinkedListTest 
{
    public static void main(String[] args) 
    {
        DuiLie d = new DuiLie();
        d.Myadd("a");
        d.Myadd("b");
        d.Myadd("c");

        while(!d.isNull())
        {
            System.out.println(d.Myget());
        }
    }
}

总结:由于LinkedList集合它具有对第一个元素和最后一个元素进行操作的方法
通过这几个方法我们可以很好的模拟出队列和堆栈数据结构

需求:将自定义的人对象添加到List集合中,并去除相同的元素
规定同姓名和同年龄为相同的人
思路:
1.先描述人
2.定义方法可以获取人的姓名和年龄
3.复写父类的equals方法,自定义比较的方法
4.提供一个去除相同元素的方法,在迭代的过程中将比较每个人,并将相同的对象去掉
5.打印集合中的元素

import java.util.*;
class Person
{   
    private String name;
    private int age ;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    //覆盖父类中的equals方法,让其按照自定义的方法进行比较
    public boolean equals(Object obj)
    {
        if(!(obj instanceof Person))
            throw new RuntimeException("类型转换异常");
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}
class ArrayListTest
{
    public static void main(String[] args) 
    {
        ArrayList a = new ArrayList();

        a.add(new Person("zhangsan",21));
        a.add(new Person("zhangsan",22));
        a.add(new Person("zhangsan",22));
        a.add(new Person("zhangsan",24));
        a.add(new Person("zhangsan",23));
        a.add(new Person("zhangsan",23));

        a = singleList(a);

        Iterator it = a.iterator();
        while(it.hasNext())
        {
            Person p = (Person)it.next();//it.next()返回的是Object,父类Object中没有getName和getAge等方法,所以需要强转
            System.out.println(p.getName()+"...."+p.getAge());
        }
    }
    /*
    去除集合中重复的元素
    思路:
    1.定义一个新的集合
    2.在用迭代器取出原集合中的对象时,判断新的集合中有没有那个对象,
    如果有则不添加,如果没有则添加
    3.将这个新的集合返回
    */
    public static ArrayList singleList(ArrayList a)
    {
        ArrayList a1 = new ArrayList();

        Iterator it = a.iterator();
        while(it.hasNext())
        {
            Object obj = it.next();

            if(!a1.contains(obj))
            /*contains底层调用的是equals方法,所以当传入的对象是自定义时,需要自定义一个equals方法,让其按照自定义的方法进行比较
            List 集合中的很多方法底层调用的都是equals方法
            */
                a1.add(obj);
        }
        return a1;
    }
}

Set集合:
Set集合是无序的且元素不可以重复
需求:往HashSet集合中存入自定义对象,并保证对象的唯一性
HashSet 集合保证元素唯一性的原理
在存入元素时首先是比较各个元素的哈希值,在哈希值相同的情况下再调用equals方法
所以在描述对象时必须覆盖父类的hashCode()和equals();

class Person
{
    private String name;
    private int age;
    Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    //覆盖父类的hashCode()方法
    public int hashCode()
    {
        System.out.println(this.name+".....hashCode.....");
        return name.hashCode()+age*12;
    }
    //覆盖父类的equals()方法
    public boolean equals(Object obj)
    {
        if(!(obj instanceof Person))
            throw new RuntimeException("类型转换异常");

        Person p = (Person)obj;
        System.out.println(this.name+"..比较.."+p.name);
        return this.name.equals(p.name) && this.age == age ;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}

TreeSet集合,可以对元素进行排序,首先对象一定要具备可比较性,可以通过实现Comparable接口让类强制具备比较性,如果默认的排序方式不是所想要的,可以自定义一个比较器,并将这个比较器作为参数传给该集合的构造函数
需求:
将传入的人对象按照年龄排序
自定义一个比较器,让人按照姓名排序

import java.util.*;
class TreeSetDemo 
{
    public static void main(String[] args) 
    {
        //如果通过构造函数传入比较器,会按照比较器进行排序
        TreeSet ts = new TreeSet(new MyCom());
        ts.add(new Person("a",35));
        ts.add(new Person("d",18));
        ts.add(new Person("a",22));
        ts.add(new Person("bb",24));

        Iterator it = ts.iterator();
        while (it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"...."+p.getAge());
        }
    }
}
class Person implements Comparable
{
    private String name ;
    private int age;
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    //实现Comparable接口,复写父类的compareTo方法,使其按照自定义的方法排序
    public int compareTo(Object obj)
    {
        if (!(obj instanceof Person))
            throw new RuntimeException("不是人对象");
        Person p = (Person)obj;

    System.out.println(this.name+".....compareTo......."+p.name);
        //基本数据类型不能调用compareTo方法,所以要将其包装成对象
        int num = new Integer(this.age).compareTo(new Integer(p.age));
        if (num==0)
            return this.name.compareTo(p.name);
        return num;
    }
    //有可能用到的是hashSet集合,所以要覆盖父类的hashCode()方法
    public int hashCode()
    {
        return this.name.hashCode()+age*12;
    }
    public boolean equals(Object obj)
    {
        if(!(obj instanceof Person))
            throw new RuntimeException("不是人对象");
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age==p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}
//自定义一个比较器,实现Comparator接口并覆盖其compare方法,可以自定义一个排序方式
class MyCom implements Comparator 
{
    public int compare(Object o1,Object o2)
    {
        Person p1 = (Person)o1;
        Person p2 = (Person)o2;
        //先比较姓名,在姓名相同的情况下在比较年龄
        int num = p1.getName().compareTo(p2.getName());
        if(num==0)
            return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));
        return num;
    }
}

总结:当对象有序并且可以重复我们可以将对象存入到List集合中
当对象无序并且不可以重复是我们可以将对象存入到Set集合中,
在选择Set集合时,如果需要对其进行排序,我们可以将其存入到TreeSet集合中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值