黑马程序员_Java基础_集合(1)

------- android培训java培训、期待与您交流! ----------

集合框架:

 为什么会出现那么多容器?
 因为每一个容器 对数据的存储方式是不一样的
 这个存储方式称之为:数据结构

 数组和集合类有何不同?
 数组虽然可以存储对象,但长度是固定的;
 集合长度是可变的,数组中可以存储基本数据类型,集合只能存储对象
 集合类的特点
 集合只用于存储对象,集合长度是可以改变的,集合可以存储不同类型的对象
 1. add方法的参数类型是Object.与便于接受任意类型对象
 2. 集合中存储的都是对象的引用(对象地址) 


Conllection 
     |--List:元素是有序的,元素可以重复,因为该集合体系有索引
        |--ArrayList:底层的数据结构使用的是数组结构。  特点:查询速度很快,但是增删稍慢,线程不同步。    1.2版本出现
        |--LinkedList:底层使用的是链表结构, 特点:增删速度很快,查询速度稍慢。
        |--Vector:底层使用的是数组数据结构。  线程同步。被ArrayList替代了。  1.0版本出现
  
     |--Set:元素是无序的,元素不可以重复



例子1:
 
public class ConllectionDemo {


    /**

     * @param args

     */

    public static void main(String[] args) {

//      base_mentod();

        metod02();


    }

    public static void metod02() {

        

        ArrayList al = new ArrayList();

        

        al.add("java01");

        al.add("java02");

        al.add("java03");

        al.add("java04");

        

        ArrayList al01 = new ArrayList();

        

        al01.add("java03");

        al01.add("java04");

        al01.add("java05");

        al01.add("java06");

        

        ///去交集,al01中只会保留和al02中相同的元素。

//      al.retainAll(al01);

        print(al);

        

        

        //al去掉与al01中相同的元素,保留剩下的元素

        al.removeAll(al01);

        print(al);

        

    }


    public static void base_mentod() {

        // 创意一个容器,使用Conllection接口的子类ArryList类进行创建

        ArrayList al = new ArrayList();


        // 1.添加元素

        al.add("java01");

        al.add("java02");

        al.add("java03");

        al.add("java04");


        // 打印集合

        print(al);


        // 2.判断元素是否存在

        print("java02时候存在:" + al.contains("java02"));

        print("集合是否为空:" + al.isEmpty());


        // 3.获取元素个数,集合长度

        print("size:" + al.size());


        // 4.删除元素

        al.remove("java02");


        // 5.清空集合

        al.clear();

        print(al);


    }


    // 打印

    public static void print(Object obj) {

        System.out.println(obj);

    }


}


 List :
 特有方法:方式可以操作的角标的方法都是该体系特有的方法
 
 add(index,element); 添加一个元素
 addAll(index,Conllection);  添加一个集合
 删
 removed(index);
 改
 set(index,element);
 查
 get(index);
 subList(from, to);
 listIterator();
 
 List集合特有的迭代器。 ListIterator是Iterator的子接口。
 
 在迭代时,不可以通过集合对象的方法操作集合中的元素。
 因为会发生ConcurrentModificationException异常
 
 所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的
 只能对元素进行判断,取出,删除的操作
如果想要其他的操作如添加、修改等,就需要使用其子接口,ListIterator
该接口只能通过List集合的listIterator方法获取(因为List集合有下标,这方法是唯一的)
ListIterator常见方法
 add(E e)  将指定的元素插入列表
 set(E e)    用指定元素替换 next 或 previous 返回的最后一个元素
 hasNext()   以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。
 next()    返回列表中的下一个元素。
 hasPrevious()     如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
 previous()   返回列表中的前一个元素。
例子2:
public class ListDemo {


    public static void main(String[] args) {

        // 创建一个容器

        ArrayList list = new ArrayList();


        list.add("1");

        list.add("2");

        list.add("3");

        list.add("4");

        

        //使用ListIterator在迭代过程中,可以进行对元素集合的操作

        ListIterator it = list.listIterator();

        System.out.println(list);

        

        //从头部来时遍历

        while(it.hasNext()){   

            Object obj = it.next();

            

            if(obj.equals("2")){

//              it.add("5");   //可以在ListIterator迭代过程中对元素进行操作

//              it.remove();

//              it.set("5");   //替换

            }

        }

        System.out.println(list);

        

        System.out.println("List hasPrevicous"+it.hasPrevious());

        

        //从尾部开始进行遍历

        while(it.hasPrevious()){

            System.out.println(it.previous());

        }


        


    }

    public static void method(){


        // 创建一个容器

        ArrayList list = new ArrayList();


        list.add("1");

        list.add("2");

        list.add("3");

        list.add("4");


        // 创建一个新的容器

        ArrayList list_1 = new ArrayList();


        list_1.add("5");

        list_1.add("6");


        // 将集合list_1添加到list中

        list.add(4, list_1);


        // 查

        Iterator ite = list.iterator();

        while (ite.hasNext()) {

            System.out.println("list:" + ite.next());

        }

        

        //改

        list.set(0, "***");

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

        

        //删除

        list.remove(0);

        System.out.println("删除第一个下标:"+list);

    }


}

例子3: 需求:去除ArrayList集合中重复的元素
public class ArrayListTest {


    /**

     * @param args

     */

    public static void main(String[] args) {


        ArrayList list = new ArrayList();

        list.add("1");

        list.add("2");

        list.add("1");

        list.add("3");

        list.add("2");

        list.add("4");

        System.out.println(list);

        //去除重复元素之后

        list = singleElement(list);

        System.out.println(list);

        

    }

    public static ArrayList singleElement(ArrayList list){

        ArrayList temp = new ArrayList();

        

        Iterator it = list.iterator();

        while(it.hasNext()){

            Object obj=  it.next();

            if(!temp.contains(obj))

                temp.add(obj);

        }

        return temp;

    }


}


 例子4:
将自定义对象作为元素存放在ArrayList集合中, 并去除重复的元素
 比如: 存人对象,同性名同年龄,视为同一个人能,为重复元素
 思路:
 对人描述,将数据封装到人对象中
 定义容器,将人存入
 取出 
class Person {

    private String name;

    private int age;


    Person(String name, int age) {

        this.name = name;

        this.age = age;

    }


    @Override

    public boolean equals(Object obj) {

        if (!(obj instanceof Person))

            return false;

        Person person = (Person) obj;

        return this.name.equals(person.name) && this.age == person.age;

    }


    public String getName() {

        return name;

    }


    public int getAge() {

        return age;

    }


}


public class ArrayListTest1 {


    public static void main(String[] args) {

        ArrayList<Person> list = new ArrayList<Person>();


        list.add(new Person("李四01", 20));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四03", 23));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四04", 24));

        

        list = singleElement(list);

        

        Iterator it = list.iterator();

        while(it.hasNext()){

            Person p = (Person) it.next();

            print(p.getName()+"---"+p.getAge());

        }


    }


    public static ArrayList singleElement(ArrayList list) {

        ArrayList temp = new ArrayList();


        Iterator it = list.iterator();

        while (it.hasNext()) {

            Object obj = it.next();

            if (!temp.contains(obj))    //这里的contains依赖Object中的equals方法

                temp.add(obj);

        }

        return temp;

    }

    public static void print(Object obj){

        System.out.println(obj);

    }


}

迭代器:  就是集合的取出元素的方式
  
  每一个容器的数据结构不同,取出的细节也是不一样的,但都是有共性内容的
  那么这些内部类都符合一个规则,该规则就是Iterator
  
 如何获取集合的去除对象?
  通过一个对外提供的方法
 iterator();
public class IteratorDemo {

    public static void main(String[] args) {

        //创建一个容器

        ArrayList list = new ArrayList();

        

        list.add("java01");

        list.add("java02");

        list.add("java03");

        list.add("java04");

//      第一中方式:

//      Iterator ite = list.iterator();  //获取迭代器

//      while(ite.hasNext())

//          System.out.println(ite.next());

        

//      第二种方式:国外流行是用,比较减少资源消耗

        for(Iterator ite = list.iterator(); ite.hasNext();)

            System.out.println(ite.next());

    }


}

LinkedList特有方法: (它都会集成List接口的所有方法,我们这里不在说,只介绍一下它特有的方法)
addFirst();
addLast();
getFirst();
getLast();
获取元素,但不删除元素。 如果集合中没有元素,会穿线NoSuchElementException异常
removeFirst();
removeLast();
获取元素,但是元素被删除。   如果集合中没有元素,会穿线NoSuchElementException异常

JDK1.6出现了替代方法:
offerFirst();
offerLast();
peekFirst();
peekLast();
获取元素,但不删除元素。 如果集合中没有元素,会返回nul
pollFirst();
pollLast();
获取元素,但是元素被删除。 如果集合中没有元素,会返回nul

public class LinkedListDemo {

    public static void main(String[] args) {

        LinkedList link = new LinkedList();

        //从第一位添加

//      link.addFirst("1");

//      link.addFirst("2");

//      link.addFirst("3");

//      link.addFirst("4");

        print(link);

//      print(link.getFirst());                 //当集合没有元素时,这个方法会抛出异常

        print(link.pollFirst());     //删除

//      print(link.getLast());

        print(link.pollLast());

//      print(link.removeFirst());  //获取并删除元素    当集合没有元素时,这个方法会抛出异常

        print(link.peekFirst());    //获取

        print(link.peekLast());

        

        

        LinkedList link1 = new LinkedList();

        //从最后以为添加

        link1.addLast("5");

        link1.addLast("6");

        link1.addLast("7");

        link1.addLast("8");

        print(link1);

//      print(link1.getFirst());

//      print(link1.getLast());

        //遍历

        while(!link1.isEmpty()){

            print(link1.removeFirst());

        }

        


    }

    

    public static void print(Object obj){

        System.out.println(obj);

    }


}


需求:使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出
队列:先进先出  (FIFO) 
 
//队列类

class Queue{

    private LinkedList link;

    Queue(){

        link = new LinkedList();

    }

    

    public void add(Object obj){

        link.addFirst(obj);

    }

    public Object  get(){

        return link.removeLast();

    }

    public boolean isNull(){

        return link.isEmpty();

    }

    

}


public class LinkedListTest {

    public static void main(String[] args) {

        Queue que = new Queue();

        que.add("1");

        que.add("2");

        que.add("3");

        que.add("4");

        

        while(!que.isNull()){

        System.out.println(que.get());

        }

        


    }


}

枚举就是Vector特有的取出方式(线程安全,但效率不高)
发现枚举和迭代器很像
其实枚举和迭代器是一样的(可以查文档看看)
因为枚举的名称以及方法的名称都过长。
所以被迭代器取代了

public class VectorDemo {

    public static void main(String[] args) {

        

        //使用Vector创建一个新的容器

        Vector vec = new Vector();

        

        vec.add("1");

        vec.add("2");

        vec.add("3");

        vec.add("4");

        

         Enumeration enu = vec.elements();

         while(enu.hasMoreElements()){

             System.out.println( enu.nextElement());

         }


    }


}
  Set:元素是无序的(存入和取出的顺序不一定一致)   元素不可以重复
 |---HashSet:顶层数据结构是哈希表
      |--hashSet是如何保证元素唯一性的呢?
           是通过元素的两个方法,hashCodeequals来完成。
           如果元素的HashConde值相同,才会判断equals是否为true
           如果元素的HashConde值不同,不会调 用equals.
 注意:对于判断元素是否存在,以及删除等操作,(依赖的方法是元素的hashCode和equals方法)
 

 |---TreeSet:
     Set集合的功能和Collection是一致的

例子:
public class HashSetDemo {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        // HashSet集合是没有重复元素的
        hs.add("1"); // 方法返回的是boolean true
        hs.add("1"); // false   重复添加的元素都无false的
        hs.add("2"); // true
        hs.add("3");// true
        hs.add("3");// false
        hs.add("4");// true
        Iterator it = hs.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

需求: 将自定义对象作为元素存放在HashSet集合中, 并去除重复的元素 

实现
public class HashSetTest {
    public static void main(String[] args) {
        HashSet hash = new HashSet();
        hash.add(new Student("lisi01", 21));
        hash.add(new Student("lisi01", 21));
        hash.add(new Student("lisi02", 22));
        hash.add(new Student("lisi03", 23));
        
        hash.contains(new Student("lisi01", 21));//true 判断集合中是否有这一元素,依赖该元素的hashCode和equals方法
        hash.remove(new Student("lisi01", 21)); // 删除也依赖该元素的hashCode和equals方法
        Iterator it = hash.iterator();
        while (it.hasNext()) {
            Student p = (Student) it.next();
            System.out.println(p.getName() + ":" + p.getAge());
        }
    }
}
class Student {
    private String name;
    private int age;
    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int hashCode() {
        return name.hashCode() + age * 37; // 这是为了让哈希表唯一(必须的*重点)
    }
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Student))
            return false;
        Student person = (Student) obj;
        return this.name.equals(person.name) && this.age == person.age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}

TreeSet:可以对Set集合中的元素进行排序
  底层数据结构是二叉树
  保证元素唯一性的依据:compareTo方法return 0.
  
  TreeSet排序的第一种方式:让元素自身具备比较性。
  元素需要实现Comparable接口,覆盖compareTo方法
  这种方式也成为元素的自然排序,或者叫做默认排序
  
  TreeSet的第二种排序方式:
  当元素自身不具备比较性是,或者具备比较性不是所需要的。
  这是就需要让集合自身具备比较性
  在集合初始化时,就有了比较方式;(创建一个类,实现Comparator比较器,复写compareTo方法,将该类放到TreeSet的构造函数中)
需求:
往TreeSet集合中存储自定义对象人
想按照人的年龄进行排序
记住,排序是,当主要条件相同时,一定判断一下次要条件 

例子1:
public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet tree = new TreeSet();
        tree.add(new People("lisi001",21));
        tree.add(new People("lisi001",21));  //去掉重复对象
        tree.add(new People("lisi002",22));
        tree.add(new People("lisi005",22));   //当年龄相同时,判断姓名进行排序
        tree.add(new People("lisi003",23));
        tree.add(new People("lisi004",24));
        
        Iterator it = tree.iterator();
        while(it.hasNext()){
            People p = (People) it.next();
            System.out.println(p.getName()+"_____"+p.getAge());
            
        }
    }
}
class People implements Comparable{   //一定要实现Comparable接口,为TreeSet排序时使用到  (重点)
    private String name;
    private int age;
    People(String name ,int age){
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Object obj) {
        if(!(obj instanceof People))
            throw new RuntimeException("不是People类对象");
        People p = (People) obj;
        
        if(this.age > p.age)
            return 1;
        if(this.age == p.age){
            return this.name.compareTo(p.name);    //当年龄相同时,还用对姓名进行排序,String类应实现了Comparable接口
        }
        return -1;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    
    
}

当元素自身不具备比较性,或者具备的比较性不是所需要的
 这时需要让容器自身具备比较性
 定义了比较器,将比较器对象作为参观传递给TreeSet集合的构造函数
 当两种排序都存在时,以比较器为主
 定义一个类,实现Comparator接口,覆盖compareTo方法 
例子2: 
 
public class TreeSetTest01 {
    public static void main(String[] args) {
        TreeSet tree = new TreeSet(new MyComparator());  //使用构造函数进行排序
        tree.add(new People01("lisi001", 21));
        tree.add(new People01("lisi001", 21)); // 去掉重复对象
        tree.add(new People01("lisi002", 22));
        tree.add(new People01("lisi005", 22)); // 当年龄相同时,判断姓名进行排序
        tree.add(new People01("lisi003", 23));
        tree.add(new People01("lisi004", 24));
        Iterator it = tree.iterator();
        while (it.hasNext()) {
            People01 p = (People01) it.next();
            System.out.println(p.getName() + "_____" + p.getAge());
        }
    }
}
class MyComparator implements Comparator{
    @Override
    public int compare(Object o1, Object o2) {
        People01 p1 = (People01) o1;
        People01 p2 = (People01) o2;
        int num = p1.getName().compareTo(p2.getName());
        //姓名相同
        if(num == 0){
            //当姓名相同时,比较年龄
            return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));   
        }
        return num;
    }
    
}
class People01 {//implements Comparable { // 一定要实现Comparable接口,为TreeSet排序时使用到 (重点)
    private String name;
    private int age;
    People01(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}


 练习:按照字符串长度排序
字符串本书具备比较性,但是它的比较方式不是锁所需要的
我们只能使用比较器

例子3:
public class TreeSetTest02 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                int num = new Integer(s1.length()).compareTo(s2.length());
                if(num == 0){
                    return s1.compareTo(s2);
                }
                    
                return num;
            }
            
        });
        
        ts.add("t");
        ts.add("ac");
        ts.add("zcf");
        ts.add("acdr");
        ts.add("acf");
        ts.add("dddd");
        
        Iterator it = ts.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值