您的位置:首页 > 职场人生

黑马程序员——集合框架

2015-06-01 15:56 417 查看
------- 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("ja
4000
va03");
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());
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: