黑马程序员——集合框架

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


集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。

java集合框架:

1. 什么是框架:类库的集合

2.集合框架:用来表示和操作的统一的架构,包含了实现集合的接口与类

3.集合:存放数据的容器

集合框架包含了两部分:一部分是接口,一部分是类

4.为什么会出现接口:因为集合框架中的很多类 功能是相似的(所以用接口来规范类)

 

java集合类是一种工具类,用于存储不定长度的数据。Java集合可以大致分为Set,List和Map三种体系,其中Set代表无序、不可重复的集合;List代表有序、重复的集合;而Map代表具有映射关系的集合。从Java5之后又增加了Queue体系集合,代表一种队列集合实现。

集合类的出现是为了在编程时保存数量不确定的数据,以及具有映射关系的数据(也就是关系数组),所以也称集合类为容器类。集合类都位于Java.util包下,为解决线程并发问题Java5之后还在Java.util.concurrent包下提供了支持多线程的集合类。其与数组不一样,数组元素可以保存基本数据类型的值,也可以是对象;而集合类只允许保存对象的引用变量。
Java中的集合类主要有两个接口派生:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。


一:常用集合类之间的层次、继承关系

Collection
|--List:元素是有序的,元素可以重复。因为飞机和体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但是增删稍慢。
|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
|--Vector:底层是数组结构,线程同步,被ArrayList替代了,因为效率低。
|--Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
|--HashSet:底层数据结构是哈希表。HashSet通过hashCode和equals判断元素是否重复。如果元素的hashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。对于判断元素是否存在,以及删除等操作依赖的方法是元素的hashCode和equals方法。
|--LinkedSet:通过hashcode确定元素的存储位置,同时通过链表确定元素的顺序。
|--TreeSet:可以对Set集合中的元素进行排序,底层数据结构是二叉树。它保证元素唯一性的依据是compareTo方法的return。TreeSet默认顺序采用的是红黑树。TreeSet允许自定义排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需的,这是就需要让集合自身具备比较性,在集合初始化时就让其具有比较性方式。
|--EnumSet:专门为枚举类设计的集合类,其中所有的元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式的指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum内部的定义顺序来决定集合元素的顺序。
|--Map:用于保存具有映射关系的数据。
|--HashMap:底层数据结构是哈希表。HashMap通过hashCode和equals判断元素是否重复。如果元素的hashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。
|--TreeMap:可以对Map集合中的元素进行排序,底层数据结构是二叉树。它保证元素唯一性的依据是compareTo方法的return。TreeSet默认顺序采用的是红黑树。TreeSet允许自定义排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需的,这是就需要让集合自身具备比较性,在集合初始化时就让其具有比较性方式。
|--EnumMap:与枚举类一起使用的Map实现,EnumMap中的所有KEY都必须是单个枚举类的枚举值。创建EnumMap的时候必须显式或隐式的指定它对应的枚举类。
|--Queue:用于模拟队列这种数据结构,不允许随机访问。
|--PriorityQueue:数据的存储不按照加入队列的顺序,而是按照队列元素的大小重新排序。因此,当取出队列元素时,取出的并不是最先加入队列元素而是最小的元素。
|--ArrayQueue:基于数组实现的是双端队列。



List:

特有方法,凡是可以操作角标的方法都是该体系特有的方法

add(intindex,Eelement);

addAll(index,Collection);

remove(index);

set(index,element);

get(index);

subList(form,to);

listIterator();

List集合特有的迭代器,ListIterator是Iterator的子接口

在迭代时,不可以通过集合对象的方法操作集合中的元素

因为会发生ConcurrentModificationException并发操作异常

所以,在迭代时,只能用迭代器的方法操作元素,可以Iterator方法是有限的

只能对元素进行判断,取出和删除的操作

如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator

该接口只能通过List集合listIterator方法获取

import java.util.*;
 
/*
 1.add方法的参数类型是Object,以便于接受任意类型对象
 2.方法中存储的都是对象的引用或者地址
 什么是迭代器呢?
 其实就是集合的取出元素的方式
 */
class CollectionDemo {
    publicstatic void main(String[] args) {
        //method_2();
        //base_method();
        get_method();
    }
 
    publicstatic void sop(Object obj) {
        System.out.println(obj);
    }
 
    publicstatic void base_method() {
        //创建一个集合容器,使用Collection接口的子类:ArrayList
        ArrayListal = new ArrayList();
        //1,添加元素
        al.add("java01");//add()参数类型是Object类型的,因为可以是任意对象
        al.add("java02");
        al.add("java03");
        al.add(4);
        sop("原集合:" + al);
        //2.获取个数,集合长度size();
        sop("size="+ al.size());
        //3.删除元素
        al.remove("java02");
        sop("改变后的集合:" + al);
        al.clear();//清空集合
        sop(al);
        //4.判断集合是否为空
        sop("判断元素是否存在" + al.contains("java01"));
        sop("判断集合是否为空" + al.isEmpty());
    }
 
    publicstatic void method_2() {
        ArrayListal1 = new ArrayList();
        al1.add("java01");//add()参数类型是Object类型的,因为可以是任意对象
        al1.add("java02");
        al1.add("java03");
        ArrayListal2 = new ArrayList();
        al2.add("java05");//add()参数类型是Object类型的,因为可以是任意对象
        al2.add("java06");
        al2.add("java04");
        al2.retainAll(al1);//取交集,al1中只会保留和al2中相同的元素
        sop("al1:"+ al1);
        sop("al2:"+ al2);
    }
 
    publicstatic void get_method() {
        ArrayListal = new ArrayList();
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add(4);
        /*
         * Iterator it = al.iterator();//返回的是Iterator接口类型的对象,Iterator是一个集合的内部类
         * while (it.hasNext()) { sop(it.next()); }
         */
        for(Iterator it = al.iterator(); it.hasNext();)// 这样写不用在迭代结束后还保留it对象,因为it是for循环的一个内部变量,便于内存管理
        {
            sop(it.next());
        }
    }
}

 

import java.util.*;
 
class ListDemo {
    publicstatic void main(String[] args) {
        //method();
        //演示列表迭代器
        ArrayListal = new ArrayList();
        //添加元素
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add(4);
        sop("原集合是:" + al);
        ListIteratorli = al.listIterator();
        while(li.hasNext()) {
            Objectobj = li.next();
            if(obj.equals("java02"))
                li.set("java006");
            if(obj.equals("java03"))
                li.add("new");
            sop("obj="+ obj);
        }
        sop(li.hasNext());
        sop(li.hasPrevious());
        sop("改变后的集合:" + al);
        //在迭代过程中,准备添加或者删除元素
        /*
         * Iterator it = al.iterator(); while(it.hasNext()) { Object obj =
         * it.next(); if(obj.equals("java02"))
         * //al.add("java008");//这步操作可能会引起并发访问异常,因为al有两种操作方式,容易产生安全隐患
         * it.remove();
         * sop("obj="+obj);//迭代过程中即使删除的元素也会被obj引用,所以也能打印出来,而且Iterator只有三个方法,有局限性
         * }
         */
    }
 
    publicstatic void method() {
        ArrayListal = new ArrayList();
        //添加元素
        al.add("java01");
        al.add("java02");
        al.add("java03");
        al.add(4);
        sop("原集合是:" + al);
        //在指定位置添加元素
        al.add(1,"java09");
        //删除指定位置的元素
        //all.remove(2);
        //修改元素
        al.set(2,"java007");
        //通过角标获取元素
        //sop("get(1):"+al.get(1));
        //sop(al);
        //获取所有元素
        for(int x = 0; x < al.size(); x++) {
            sop("al("+ x + ")=" + al.get(x));
        }
        Iteratorit = al.iterator();
        while(it.hasNext()) {
            sop(it.next());
        }
        //通过indexOf获取对象的位置
        sop("index="+ al.indexOf("java09"));
        Listsub = al.subList(1, 4);
        sop("sub="+ sub);
    }
 
    publicstatic void sop(Object obj) {
        System.out.println(obj);
    }
}


 

import java.util.*;
 
/*
 LinkedList:特有方法
 addFist();
 addLast();
 getFirst();
 getLast();
 removeFirst();
 removeFirst();
 JDK1.6以后出现了替代方法:
 offerFirst();
 offerFirst();
 peekFirst();
 peekLast();如果没有元素,则返回null
 pollFirst();
 pollLast();如果没有元素,则返回null
 */
class LinkedDemo {
    publicstatic void main(String[] args) {
        LinkedListlink = new LinkedList();
        link.addFirst("java01");
        link.addFirst("java02");
        link.addFirst("java03");
        link.addFirst("java04");
        sop(link);
        sop(link.getFirst());
        sop(link.getLast());
        sop(link.size());
        sop(link.removeFirst());
        sop(link.size());
        while(!link.isEmpty()) {
            sop(link.removeFirst());
        }
    }
 
    publicstatic void sop(Object obj) {
        System.out.println(obj);
    }
}


 

Map集合:该集合存储键值对一对一对往里存而且要保证键的唯一性

1.添加

put(Kkey,Vvalue)

putAll(Map<?extendsK,?extendsV>m)

2.删除

clear()

remove(Objectkey)

3.判断

containsKey(Objectvalue)

containsValue(Objectvalue)

isEmpty()

4.获取

size()

values()

get(Objectkey)

keySet()

entrySet()

 

Set:无序,不可以重复元素

--HashSet:数据结构是哈希表,线程是非同步的

保证元素唯一性的原理,判断元素的hashCode值是否相同

如果相同,还会继续判断元素的equals方法,是否为true

--TreeSet:可以对Set集合中的元素进行排序

底层数据结构是二叉树

1,保证元素唯一性的依据compareTo方法return0。

2,当元素不具备比较性时,或者具备的比较性不是所需要的

这时就需要让集合自身具备比较性

在集合初始化时,就有了比较方式

需求;

往TreeSet集合中存储自定义对象学生

想按照学生的年龄进行排序

记住:排序时,当主要条件相同时,一定判断次要条件

import java.util.*;
 
class TreeSetDemo {
    publicstatic void main(String[] args) {
        TreeSetts = new TreeSet();
        ts.add(newStudent("lisi02", 22));
        ts.add(newStudent("lisi007", 20));
        ts.add(newStudent("lisi09", 19));
        ts.add(newStudent("lisi08", 19));
        Iteratorit = ts.iterator();
        while(it.hasNext()) {
            Studentstu = (Student) it.next();
            System.out.println(stu.getName()+ "::" + stu.getAge());
        }
    }
}
 
class Student implements Comparable// 该接口强制让学生具备比较性
{
    privateString name;
    privateint age;
 
    Student(Stringname, int age) {
        this.name= name;
        this.age= age;
    }
 
    publicint compareTo(Object obj) {
        if(!(obj instanceof Student))
            thrownew RuntimeException("不是学生对象");
        Students = (Student) obj;
        System.out.println(this.name+ "::compare to::" + s.name);
        if(this.age > s.age)
            return1;
        if(this.age == s.age) {
            returnthis.name.compareTo(s.name);
        }
        ;
        return-1;
    }
 
    publicString getName() {
        returnname;
    }
 
    publicint getAge() {
        returnage;
    }
}
 


Map

Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的

HashMap:底层是哈希表数据结构允许使用null值和null键该集合是不同步的

TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序

和Set很像

Set底层就是使用了Map集合


map集合的两种取出方式

1.Ser<k>keySet:将map中所有的键存入到Set集合,因为Set集合具备迭代器,

所以可以用迭代方式取出所有的键,再根据ger方法,获取每一个键对应的值

 

Map集合的取出原理:将map集合转换成set集合再通过迭代器取出

import java.util.*;
 
public class MapDemo2 {
    publicstatic void main(String[] args) {
        Map<String,String> map = new HashMap<String, String>();
        map.put("02","zhangshan02");
        map.put("03","zhangshan03");
        map.put("01","zhangshan01");
        map.put("04","zhangshan04");
        //先获取map集合的所有键的Set集合,keySet();
        Set<String>keySet = map.keySet();
        //有了Set集合,就可以获取其迭代器
        Iterator<String>it = keySet.iterator();
        while(it.hasNext()) {
            Stringkey = it.next();
            //有了键可以通过map集合的get方法获取其对应的值
            Stringvalue = map.get(key);
            System.out.println("key--"+ key + ",value" + value);
        }
    }
}


2.Ser<Map.Entry<k,v>>entrySet:将map集合中的映射关系存入到了set集合中,

而这个关系的数据类型就是:Map.Entry

 

对于HashSet和TreeSet它们的排序是如何进行的呢?
覆盖compareTo的方法
TreeSet 是否用的二叉树算法插入数据?
hashcode()与 equals()
hashcode 重写一般只有用于集合的时候才有用
equals() 则是判断调用方法
HashSe  与 TreeSet  类示例

import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;
 
public class HashSetTest {
    publicstatic void main(String[] args) {
        Perp1 = new Per(12);
        p1.idCard= "1";
        Perp2 = new Per(33);
        p2.idCard= "1";
        HashSet<Per>hs = new HashSet<Per>();
        hs.add(p1);
        hs.add(p2);
        p2.idCard= "3";
        System.out.println(hs.size());
        Iterator<Per>it = hs.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
        Perp3 = new Per(22);
        Perp4 = new Per(15);
        Perp5 = new Per(17);
        //实现 Comparator接口 设置排序方式
        TreeSet<Per>ts = new TreeSet<Per>(new Comparator<Per>() {
            @Override
            publicint compare(Per o1, Per o2) {
                //TODO Auto-generated method stub
                returno1.age - o2.age;
            }
        });
        ts.add(p1);
        ts.add(p2);
        ts.add(p3);
        ts.add(p4);
        ts.add(p5);
        System.out.println(ts.size());
        Iterator<Per>it2 = ts.iterator();
        while(it2.hasNext()) {
            System.out.println(it2.next());
        }
    }
}
 
class Per {
    StringidCard;
    Stringname;
    intage;
 
    publicPer() {
 
    }
 
    publicPer(int age) {
        this.age= age;
    }
 
    @Override
    publicint hashCode() {
        finalint prime = 31;
        intresult = 1;
        result= prime * result + ((idCard == null) ? 0 : idCard.hashCode());
        returnresult;
    }
 
    @Override
    publicboolean equals(Object obj) {
        if(this == obj)
            returntrue;
        if(obj == null)
            returnfalse;
        if(getClass() != obj.getClass())
            returnfalse;
        Perother = (Per) obj;
        if(idCard == null) {
            if(other.idCard != null)
                returnfalse;
        }else if (!idCard.equals(other.idCard))
            returnfalse;
        returntrue;
    }
 
    @Override
    publicString toString() {
        return"Per [idCard=" + idCard + ", name=" + name + ",age=" + age + "]";
    }
}


集合框架中的工具类

Collections
对集合进行查找
取出集合中的最大值,最小值
对List集合进行排序
……
Arrays
将数组转成List集合
对数组进行排序

public static void main(String[] args){ 
       char[] c = new char[]{'A','c','B','d','E'}; 
       int[] b = new int[]{1,32,22,11,35,21,9,8}; 
        //如果数组类型是基本类型数组 则转成的list集合 没有数据  因为无法对基本类型进行泛型 
       List ls =  Arrays.asList(c);  //转换成list 集合 
       System.out.println(ls.size()); 
       Arrays.sort(c); //排序 
       System.out.println(Arrays.toString(c)); 
       Arrays.sort(b); 
       int i  = Arrays.binarySearch(b,35);; //使用二分法查找 必须先排序 才可以查找该元素 
       System.out.println(Arrays.toString(b)); 
       System.out.println(i); 
} 


 

1、两个对象值相同(x.equals(y)==true),但却可有不同的hashcode,这句话对不对?

对。

如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。

如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。


2、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常?

public class Parent implementsComparable {
    privateint age = 0;
    publicParent(int age){
        this.age= age;
    }
    publicint compareTo(Object o) {
        //TODO Auto-generated method stub
        System.out.println("methodof parent");
        Parento1 = (Parent)o;
        returnage>o1.age?1:age<o1.age?-1:0;
    }
 
}
 
public class Child extends Parent {
 
    publicChild(){
        super(3);
    }
    publicint compareTo(Object o) {
 
            //TODO Auto-generated method stub
            System.out.println("methodof child");
//          Childo1 = (Child)o;
            return1;
 
    }
}
 
public class TreeSetTest {
 
    /**
     * @param args
     */
    publicstatic void main(String[] args) {
        //TODO Auto-generated method stub
        TreeSetset = new TreeSet();
        set.add(newParent(3));
        set.add(newChild());
        set.add(newParent(4));
        System.out.println(set.size());
    }
 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值