黑马程序员-【集合框架】
来源:互联网 发布:网络冗余设计 编辑:程序博客网 时间:2024/05/24 04:18
-------android培训、java培训、期待与您交流! ----------
一、什么是集合框架
如果要保存一组对象,按照之前的的做法只能使用对象数组,但是使用对象数组有一个限制,就是数组有长度的限制,而通过一些数据结构操作,如链表,可以完成动态数
组的操作,但这些如果全部由开发人员来做是比较麻烦的,
集合框架的出现就解决的以上的难题,所谓的集合框架就是一个动态的对象数组,是对一些实现好的数据结构进行了包装,这样在使用时就会非常方便而且长度也不会像数
组那样有所限制,可见集合框架就是对一种对象容器,通过对一些数据结构的封装,可以很好的实现对对象的存取操作。
集合类都位于Java.util包下,为解决线程并发问题Java5之后还在Java.util.concurrent包下提供了支持多线程的集合类。其与数组不一样,数组元素可以保存基本数据类型的
值,也可以是对象;而集合类只允许保存对象的引用变量。
集合框架主要有两个接口:Collection和Map,这两个接口是java集合框架的根接口,这两个接口又包含了一些子接口或实现类,其中Collection接口的主要Set子接口和List子接口,其中Set中数据是无序,且不可重复的,List中的数据有序,且可以重复。Map代表具有映射关系的集合,有两个具有映射关系的数据组成,
二、集合类之间的层次关系
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:基于数组实现的是双端队列。
三、集合类常见方法
1、Collection接口的常见方法
1)添加
Boolean add (Object obj);
Boolean add(Collection cool)
2)删除
Boolean remove (object obj)
Boolean removeAll(Collection coll)
Void clear();
3)判断
Boolean contains(Object obj)
Boolean containsAll(collection coll)
Boolean IfEmpty():判断集合中是否有元素
4)获取
Int size();
Iteratot iterator() :取得元素的方法 迭代器
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同,所以该迭代器对象是在容器中进行内部实现的,对于使用容器者而言,具体的实现不重要,只要通过容器获取
到该实现的迭代器的对象即可,也就是iterator方法
Iterator接口就是对所有的Collection容器进行元索取出的公告接口
5)其他
Boolean retainAll(Collection coll) 取得交集
Object[] toArray() 将集合转成数组
2、list特有的常见方法:有一个同性特点就是可以操作角标
1)添加
Void add(index,element)
Void add(index,collection)
2)删除
Object remove(index,element)
3)修改
Object set(index,element)
4)获取
Object get(index)
Int indexOf(object)
Int lastIndexof(object)
List subList(from,to)
3、LinkedList 基本方法:
1、addFirst 2、addlast
3、getFirst(获取第一个但是不删除 没有第一个元素时抛出异常) 4、getLast
5、removeFirst(获取并删除)
1.6版本的新特性 :
peekFirst与getFirst的区别是取得元素为空时,不会抛出异常
集合类的方法如下:
import java.util.*;/* 1.add方法的参数类型是Object,以便于接受任意类型对象 2.方法中存储的都是对象的引用或者地址 */class CollectionDemo {public static void main(String[] args) {// method_2();// base_method();get_method();}public static void sop(Object obj) {System.out.println(obj);}public static void base_method() {// 创建一个集合容器,使用Collection接口的子类:ArrayListArrayList al = 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());}public static void method_2() {ArrayList al1 = new ArrayList();al1.add("java01");// add()参数类型是Object类型的,因为可以是任意对象al1.add("java02");al1.add("java03");ArrayList al2 = new ArrayList();al2.add("java05");// add()参数类型是Object类型的,因为可以是任意对象al2.add("java06");al2.add("java04");al2.retainAll(al1);// 取交集,al1中只会保留和al2中相同的元素sop("al1:" + al1);sop("al2:" + al2);}public static void get_method() {ArrayList al = 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.*;/* 1.add方法的参数类型是Object,以便于接受任意类型对象 2.方法中存储的都是对象的引用或者地址 */class CollectionDemo {public static void main(String[] args) {// method_2();// base_method();get_method();}public static void sop(Object obj) {System.out.println(obj);}public static void base_method() {// 创建一个集合容器,使用Collection接口的子类:ArrayListArrayList al = 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());}public static void method_2() {ArrayList al1 = new ArrayList();al1.add("java01");// add()参数类型是Object类型的,因为可以是任意对象al1.add("java02");al1.add("java03");ArrayList al2 = new ArrayList();al2.add("java05");// add()参数类型是Object类型的,因为可以是任意对象al2.add("java06");al2.add("java04");al2.retainAll(al1);// 取交集,al1中只会保留和al2中相同的元素sop("al1:" + al1);sop("al2:" + al2);}public static void get_method() {ArrayList al = 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.*;/* 1.add方法的参数类型是Object,以便于接受任意类型对象 2.方法中存储的都是对象的引用或者地址 */class CollectionDemo {public static void main(String[] args) {// method_2();// base_method();get_method();}public static void sop(Object obj) {System.out.println(obj);}public static void base_method() {// 创建一个集合容器,使用Collection接口的子类:ArrayListArrayList al = 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());}public static void method_2() {ArrayList al1 = new ArrayList();al1.add("java01");// add()参数类型是Object类型的,因为可以是任意对象al1.add("java02");al1.add("java03");ArrayList al2 = new ArrayList();al2.add("java05");// add()参数类型是Object类型的,因为可以是任意对象al2.add("java06");al2.add("java04");al2.retainAll(al1);// 取交集,al1中只会保留和al2中相同的元素sop("al1:" + al1);sop("al2:" + al2);}public static void get_method() {ArrayList al = 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());}}}
四、集合类的一些特点
1、栈和队列的特点
堆栈:先进后出 First In Last Out FILO
队列:先进先出 First In First Out FIFO
2、set集合:元素不可以重复,是无序的。
set接口中的方法和Collection一致
1)hashset :内部结构是hash表 是不同步的
2)treeset:
hash表内部构成:
根据专门的算法(hash算法)确定位置
hash表如何判断元素是否相同
1、判断两个元素的哈希值是否相同
2、当哈希值相同时再判断两个元素内容是否相同
(判断哈希值相同,用的是对象的hashcode方法,判断内容用的是equals方法 )
3、自己定义的类,应该重新 hashcode() 和 equals() 方法
contains方法也是根据equals方法判断元素是否相同
(不同对象的判断方法是不同的)
Hashset子类LinkedHashSet:是哈希表和链表的结合
4、TreeSet的特点:
可以对Set集合中的元素进行制定排序,是不同步的
TreeSet集合不根据hashset和equals判断元素唯一性,而是根据比较方法返回结果是否为0,是0就是相同元素,不存
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,就需要实现comparable接口,和覆盖compareTo方法
如果不要按照对象中具备的自然顺序进行排序,如果对象中不具备自然排序,怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数
实例:
import java.util.Comparator;import java.util.HashSet;import java.util.Iterator;import java.util.TreeSet;public class HashSetTest {public static void main(String[] args) {Per p1 = new Per(12);p1.idCard = "1";Per p2 = 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());}Per p3 = new Per(22);Per p4 = new Per(15);Per p5 = new Per(17);// 实现 Comparator接口 设置排序方式TreeSet<Per> ts = new TreeSet<Per>(new Comparator<Per>() {@Overridepublic int compare(Per o1, Per o2) {// TODO Auto-generated method stubreturn o1.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 {String idCard;String name;int age;public Per() {}public Per(int age) {this.age = age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((idCard == null) ? 0 : idCard.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Per other = (Per) obj;if (idCard == null) {if (other.idCard != null)return false;} else if (!idCard.equals(other.idCard))return false;return true;}@Overridepublic String toString() {return "Per [idCard=" + idCard + ", name=" + name + ", age=" + age + "]";}}
Map集合
一次添加一对元素,Collection一次添加一个元素
map也可以成为双列集合,Collection集合成为单例集合
其实map集合中存储的就是键值对
map集合中必须保证键的唯一性
常用方法:
1、添加
Value put():返回前一个和key关联的值,如果没有返回null
2、删除
Void clear();清空map集合
Value remove(key) 根据制定的key删除这个键值对
3、判断
Boolean containsKey(key)
Boolean containsvalue(value)
boolean isEmpty();
4、获取
Value get(key) :通过键获取值,如果没有该键返回null
当然可以通过返回null,来判断是非包含制定键
Int size():获取键值对的个数
Map常用的子类
|--HashTable :内部结构是哈希表,是同步的。不允许null作为建,nul作为值
|--LinkedHashMap:是有序的
|--Properties:用来储存键值对型的配置文件的信息,可以和IO技术相结合
|--HashMap:内部结构是哈希表,不是同步的。允许null作为键,null作为值
|--TreeSet:内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。
Map集合的取出原理:将map集合转换成set集合再通过迭代器取出
import java.util.*;public class MapDemo2 {public static 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()) {String key = it.next();// 有了键可以通过map集合的get方法获取其对应的值String value = map.get(key);System.out.println("key--" + key + ",value" + value);}}}
五、新特性
1、泛型
JDK1.5出现的新特性,安全机制
好处:
1、将运行时期的问题ClassCastException转到了编译时期
2、避免了强制转换的麻烦。
3、提高了编译时期的安全
<>什么时候用?当操作的引用数据类型不确定的时候,就使用<>,将要操作的引用数据类型传入即可,其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。
泛型技术是给编译器使用的技术,用于编译时期,确保了时期的安全
运行时,会将泛型去掉,生成的Class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行时的类加载器,为了解决擦除后的强转类型问题,增加了补偿程序,根据传入的元素类型,进行转换
泛型的补偿:在运行时,通过获取元素的类型进行转换动作,不用使用者再强制转换了。
泛型在集合中的应用比较广泛,其他应用较少
在JDK1.5后,使用泛型未接受类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
可以将将泛型定义在方法上
当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,只能讲泛型定义在方法上
泛型接口,将泛型定义在接口上
泛型可以对类型进行限定
? Extend E,接收E类型或者E的子类型对象。上限!
? Super E:接收E类型或者E的父类型,下限
什么时候用下线呢?通常对集合中的元素进行取出操作时,可以使用下限
2、Foreach 语句:
格式:For(类型 变量 :Collection集合|数组)
传统for和高级for的区别?
传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
高级for是一种简化形式。
它必须有被遍历的目标。该目标要是数组,要么是Collection单例集合
对数组的遍历如果仅仅是获取数组中的元素,可以使用高级for
如果要对数组的角标进行操作建议使用传统for
3、函数的可变参数。
其实就是就是一个数组,但是接收的是数组的元素
自动将这些元素封装成数组,简化了调用者的书写
注意:可变参数类型,必须定义在参数列表的结尾
六、常见问题
1、两个对象值相同(x.equals(y)== true),但却可有不同的hashcode,这句话对不对?
对。
如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。
如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。
2、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!
public class Parent implements Comparable {private int age = 0;public Parent(int age){this.age = age;}public int compareTo(Object o) {// TODO Auto-generated method stubSystem.out.println("method of parent");Parent o1 = (Parent)o;return age>o1.age?1:age<o1.age?-1:0;}}public class Child extends Parent {public Child(){super(3);}public int compareTo(Object o) {// TODO Auto-generated method stubSystem.out.println("method of child");//Child o1 = (Child)o;return 1;}}public class TreeSetTest {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubTreeSet set = new TreeSet();set.add(new Parent(3));set.add(new Child());set.add(new Parent(4));System.out.println(set.size());}}
- 黑马程序员:集合框架
- 黑马程序员-集合框架
- 黑马程序员-集合框架
- 黑马程序员:集合框架
- 黑马程序员-----集合框架
- 黑马程序员: 集合框架
- 黑马程序员-集合框架
- 黑马程序员--集合框架
- 黑马程序员- 集合框架
- 黑马程序员-集合框架
- 黑马程序员--------集合框架
- 黑马程序员----集合框架
- 黑马程序员 集合框架
- 黑马程序员 集合框架
- 黑马程序员:集合框架
- 黑马程序员-集合框架
- 黑马程序员----------------------集合框架
- 黑马程序员 集合框架
- git 使用笔记一
- 精美js鼠标特效代码跟随
- IOS 基于APNS消息推送原理与实现(JAVA后台)
- javascript中call()和apply()
- MEIZU MX4连接不上adb
- 黑马程序员-【集合框架】
- KI码
- javaScript document对象详解
- Leetcode: Department Highest Salary
- DecimalFormat 数据格式化类的使用小结
- ios多语言本地化
- 怎样在spring官网上下载spring的zip包
- Android JNI开发指南
- android开发工具下载