在EditPlus 中编写,为保持格式就插入到代码
集合框架(重点) ----------------------------------------------------------------------- Collection 位于 java.util 包中,是集合体系的一个超级接口;一个Collection代表一组Object,即Collection的元素(Elements)。 Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如 List 和 Set. List&Set 还有另外一个超级接口(Iterable)"1.5新特性";位于java.lang包中;实现这个接口允许对象成为 "foreach" 语句的目标。 "迭代器"是一种设计模式;Iterator是Java迭代器最简单的实现。 Iterator (迭代器&超级接口) 用于取代 Enumeration 枚举接口,迭代器相比枚举要更加灵活性高效 //可以对元素"判断、取出、删除"操作Iterator;在集合中采用内部类的设计,通过一个对外提供的方法iterator();获取集合对象 ListIterator extends Iterator List 特有的迭代器,相比 Iterator 更加强大,可以对元素"添加、修改";并且可以"双向遍历" 设计模式之——"迭代器模式" 定义:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。 应用示例: Iterator it = list.iterator(); while (it.hasNext()){ ... it.next() ...;//对元素进行操作 } ------------------------------------------------------------------ "List" 集合:子类 ArrayList & LinkedList //List可以操作角标index,能够精确的控制每个元素插入的位置 ArrayList(数组结构) 查询快,增删慢;线程不同步 Vector(数组结构&使用枚举) synchronized 线程同步,效率要比 ArrayList 低 数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引快插入慢 LinkedList(链表结构)查询快,增删慢;额外的方法:链表操作 add&get&removeFirst/Last(); 1.6版本出现了替代操作 LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快! LinkedList 的特有方法使其可以当作堆栈、队列和双向队列使用。这些方法没有在任何接口或基类中定义过 【总结】 List元素判断元素是否相同,依据的是equals方法;ArrayList、LinkedList都是依赖于equals进行判断 查看JDK的源码可以发现: contains()的判断调用了indexOf()方法(return indexOf(o) != -1;),indexOf又依赖于equals方法(if (o.equals(x.item)) return index;), 默认调用的是Object的equals方法,每一个元素的调次数 是由临时容器中的元素个数决定的; String类以及基本数据类型都在类中复写了equals,所以在判断时函数自动覆盖,不需要再复写; 而用对象做比较时,如果该类没有复写equals方法,默认调用的是Object的equals;判断的是对象的地址值(即是否同一个对象); 而如果判断的是对象的属性是否重复,就需要复写equals方法,使调用contains时默认重载; 在remove()对象时,也会调用equals()方法, ------------------------------------------------------------------------------ "Set" 集合:子类 HashSet & TreeSet Set 元素是无序的,集合中元素不能重复; Set 集合没有特殊方法,功能完全继承自 Collection HashSet 底层数据结构是哈希表;能够快速定位一个元素;通过 (boolean)(hashCode && equals) 方法保证唯一性,两个结果都相同就证明是同一个元素 在hashSet中对元素contains、remove等操作时,先判断hashCode,再判断equals;而在ArrayList中对元素的操作只依赖于equals方法 所以使用HashSet集合时一般都要在对象所属类中覆盖hashCode方法和equals方法 (默认继承自Object) TreeSet 底层数据结构为二叉树 会对集合中元素进行排序,该集合的元素首先要有比较性 排序的两种方式: 1)让元素自身具备比较性,由元素继承java.lang 包中的"Comparable"接口;此接口强行对实现它的每个类的对象进行整体排序。 这种排序被称为类的自然排序,类的"compareTo"方法被称为它的自然比较方法。 2)元素不具备比较性,或者具备的比较性不能满足需要; 这时就让集合具备比较性; 定义比较器,使集合在初始化时就具备比较方式 由比较器继承java.util包中的"Comparator"接口,实现"compare"方法 使用示例://方法1,使元素自身具备比较性 import java.lang.Comparator; //导包 class Person implements Comparable{ //对元素操作 public int compareTo(Object obj){...} } //在存入集合中时会自动排序 TreeSet ts = new TreeSet(); ts.add(.)... //添加时元素自动比较排序 //方法2:使集合具备比较性,自定义一个比较器,作为TessSet集合构造时的参数 import java.util.Comparator; class myCompare implements Comparator{ //自定义比较器 public int compare(Object o1 , Object o2){...} } //使TreeSet集合在构造时就具备比较器定义的功能,元素可以不具备比较性 TreeSet ts = new TreeSet(new myCompare()); ts.add(.)... //添加时集合对元素进行比较 【小结:Comparable & Comparator 的区别】 二者都是接口,需要被实现,但是Comparable是被对象实现,comparator是被比较器实现 Comparable 是一个对象本身就已经支持自比较所需要实现的接口,(如 String、Integer 等数据类对象自己就可以完成比较大小操作,已经实现了Comparable接口)可以直接使用CompareTo()方法进行比较;而一般对象需要继承该接口,实现compareTo()方法后才能然后完成比较。如Student类需要继承Comparable接口 Comparator 可以看成一种算法的实现,将算法和数据分离; 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。将比较器对象传入TreeSet的构造函数来调用 Comparable 位于java.lang 包中,是对其子类元素属性的改变; Comparator 位于java.util包中,是一个专门作用于TreeSet集合的工具接口 简单来说:"一个是自已完成比较,一个是外部程序实现比较。" 当两种排序都存在时,优先使用比较器的规则,Comparator的使用更加灵活,不需要对对象进行修改 另:可以发现使用二叉树数据结构的集合都需要进行排序,有必要具备比较性。如(TreeSet&TreeMap) --------------------------------------------------------------- Map 集合 Map 集合的存储方式是以(key value)"键值对"的形式存在的;而 Collection 的一个元素只是一个值 "键"是唯一的,"值"可以重复; Map 集合可以多层嵌套形成多级映射,即:Map集合的value 可以是一个集合 Map 的子类 Hashtable 哈希表结构,不允许 null 键/值;线程同步; 效率较低 1.0 版本 子类 Properties 表示可以在io流中加载的字符串属性集 (系统属性) HashMap 哈希表结构,可使用 null 键/值;线程不同步,效率较高 1.2 版本 类似于 HashSet; 需要复写hashCode与equals方法 TreeMap 二叉树结构,线程不同步,可以给"键"进行排序,使用方法与 TreeSet 集合类似,需要具有比较性 注意:Map没有继承 Collection, 与 List&Set 不同,方法也有区别 Map 类似于 Set; Set 集合在底层就应用了 Map 集合 Map 集合的两种取出方法:"keySet"和"entrySet" ketSet: 将Map集合的"key"转成Set集合 (键符合Set集合的元素唯一性),再通过Collection的迭代器取出"key";通过"key"获取"value" entrySet: 将Map集合中的映射关系存入到set集合中; 这个关系的数据类型是Map.Entry, Map.Entry中的 Entry是一个接口,是Map接口的一个内部接口 使用示例: Map<k,v> map = new HashMap<k,v>(); map.put(k. , v.)... //创建Map集合并添加元素 //1,keySet 方法 Set<k> keySet = map.keySet();//该方法创建一个存储Map集合中的"key"的Set集合 Iterator<k> it = keySet.iterator();//迭代Set集合获取key while(it.hasNext()){ k key = it.next(); v value = map.get(key);//通过key获取value } //2,entrySet方法 Set<Map.Entry<k,v>> entrySet = map.entrySet();//该方法创建一个存储Map集合中映射关系的Set集合 Iterator<Map.Entry<k,v>> it = entrySet.iterator(); //依然是迭代获取 while(it.hasNext()){ Map.Entry<k,v> me = it.next(); me.getKey(); me.getValue(); //获取键和值的操作 } ----------------- "Map.Entry" 表示一种数据类型,key和value存在映射"关系";Map.Entry 正是为了描述这种关系而存在 "Entry 是 Map接口的一个内部接口" 在源码中的实现示例: interface Map { public static interface Entry { //内部接口,static是局部修饰符,看到static就可以联想到该接口是内部接口 public abstract Object getKey(); public abstract Object getValue(); } } class HashMap implements Map { class haha implements Map.Entry { //内部类 public Object getKey(){...} public Object getValue(){...} } } ------------------------------------------------------------------------- ------------------------------------------------------------------------- 集合注意事项: 1)Collection 没有get()方法来取得某个元素。只能通过iterator()或"高级for"遍历获取元素 2)Set 和Collection拥有一模一样的接口 3)List 可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...(add/get) 4)一般使用 ArrayList 用 LinkedList 构造堆栈stack、队列queue。 5)Map 用put(k,v)/get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value 6)Map 中元素,可以将key序列、value序列单独抽取出来。使用keySet()抽取key序列,将map中的所有keys生成一个Set。 使用values()抽取value序列,将map中的所有values生成一个Collection。 为什么一个生成Set,一个生成Collection?因为"key是独一无二的,value允许重复"。 "数组与集合的区别" Java所有"存储及随机访问一连串对象"的做法,数组是最有效率的一种。可以存储基本数据类型 但是数组的局限性也很明显:容量固定且无法动态改变;还有一个缺点是,无法判断其中实际存有多少元素,length只是告诉我们array的容量 集合的长度可变; List&Set&Map 将持有元素一律视为"Object"类型; Collection(List&Set)与 Map 都是接口,不能实例化,只有其子类才能被实例化 数组与集合都有对应的工具类, Arrays&Collections "Collections" 类提供的静态方法能够对List集合进行排序、二分查找、替换、反转、混洗等操作 通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。 "Arrays"类 提供了一些静态方法来对数组进行操作。(用法参见API文档) 此外在java.lang.reflect 包中有 Array 类用来对数组进行反射操作,要注意和 Arrays 类区分 "数组与集合的互转" 数组转集合: Arrays.asList(array); //为了使用集合的方法对数组元素操作 集合转数组:list.toArray(); //1)空参 为了限制对元素的操作(禁止增删等) list.toArray(T[] a);//2)实参 返回数组的运行时类型与指定数组的运行时类型相同。 要注意:集合转数组使用的是继承自 Collection 接口的自带方法,不是 Collections 工具类提供的方法 集合可以直接打印,数组需要通过工具类的方法 Arrays.toString(一维) 或者 deepToString(多维)来打印