Java集合框架学习笔记
集合类的由来:
对象用于封装特有数据,对象多了需要存储,如果对象的长度不确定,就使用集合存储。
集合特点
1、用于存储对象的容器。
2、集合的长度可变。
3、集合中不可以存储基本类型
集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取就形成了集合框架
框架的顶层就是:Collection接口。
顶层抽出的共有方法:
1、添加
2、删除
3、判断
4、获取
Iterator iterator();获取元素的方式 :迭代器
迭代器的使用:
使用for循环节省内存 循环结束后it不会驻留在内存中
如果用While 迭代器会驻留在内存中
for(Iterator it = coll.iterator();it.hasNext();){
System.out.println(it.next());
}
迭代器原理:
该对象必须依赖于具体容器,因为每一个容器的数据结构都不相同。
所以该迭代器对象是在容器中进行内部实现的。
对于使用容器者而言,具体的实现并不重要,只要通过容器获取到该实现的迭代器的对象即可。
也就是iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口
MyEclipse快捷键:
查看接口的实现类:Ctrl+T
查看类或方法的引用 Ctrl+Shift+G
查看类的声明:F3
5、其它
retainAll(Collection coll) 获取两个集合中的交集
注意:retainAll与removeAll,removeAll删除集合中含有的所有对象.
eg:c1={1,2,3} c2={2,3,4} 吧c2放入c1中 removeAll后得到{1}
retainAll后{2,3}
Collection 下面的两个重要的子接口:
|--List:有序(存入和读出的顺序一致),元素都有索引,元素可以重复
|--Set:元素不能重复。(与List最大不同) 无序(也有可能出现有序的)
List:常见方法-->Collection有的List都有
特有方法:
修改:Object set(index,element);
获取:Object get(index);
int indexOf(Object o);
int lastIndexOf(Object o);
List<E> subList(int fromIndex, int toIndex);(包头不包尾)
总结:List可以对元素进行增删改查
注意:进行集合操作时候不进行迭代操作,进行迭代操作时候不进行集合操作
否则会出现对该对象进行了并发修改,但是不允许修改时候会报这种错误
改进方法-->迭代的时候不要使用iterator();方法。要使用listIterator();方法进行迭代
此方法为Iterator接口下面的子接口的方法的实现。
List接口下面的实现类:
|--Vector:(内部数据结构为数组数据结构,是同步的,意味着线程安全,但是效率低,现在已经基本上不用)注:最早的单列集合
Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。
但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。
增删查都很慢
遍历Vector的方法有三种(较ArrayList和LinkedList多出一种)
枚举遍历:
Enumeration en = Vector.elments();
Enumeration 有两个方法 hasMoreElement();nextElement()
while(vector.hasMoreElements()){ System.out.println(vector.nextElement) }
关于Enumeration:
此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。
新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。
|--ArrayList(内部数据结构为数组数据结构,是不同步的。效率高。所以替代了Vector。如果是多线程 给ArrayList加锁)
可变长度数组实现原理,ArrayList会提前生成一个固定长度数组,如果大小不够大,新生成一个数组增加原来数组的一半。
读、查询速度快
|--LinkedList(内部数据结构为链表,非同步,效率高)
增删元素速度快
特有方法:addFrist(); addLast();
理解:因为LinkedList内部数据结构为链表,所以中间都是一环扣一环,但是头和尾部不是,所以很好添加新元素。
getFirst();获取但不删除 removeFirst();获取但是删除
重点:用LinkedList模拟堆栈或者队列的数据结构
堆栈:
栈特点:先进后出
队列:
特点:先进后出
实现:描述一个容器,给使用者提供一个容器对象完成这两种结构中的一种。
class MyQuere{
private LinkedList link;
MyQuere{
link = new LinkedList();
}
public void myAdd(Object obj){
link.addLast(obj);
}
public Object myGet(){
return link.removeFirst();
}
public boolean isNull(){
return link.isEmpty();
}
}
class MyStack{
private LinkedList link;
MyQuere{
link = new LinkedList();
}
public void myAdd(Object obj){
link.addLast(obj);
}
public Object myGet(){
return link.removeLast();
}
public boolean isNull(){
return link.isEmpty();
}
}
LinkdList---->JDK1.6新特性与1.5对比
addFirst();addLast();-->无返回
offerFirst();offerLast(); -->在此列表插入指定的元素。返回:true(根据 Deque.offerFirst(E) 的规定)(1.6新特性)
getFirst();getLast(); -->NoSuchElementException - 如果此列表为空.
peekFirst();peekLast(); -->此列表的第一个元素;如果此列表为空,则返回 null.(1.6新特性)
removeFirst();removeLast(); -->无返回
pollFirst();pollLast(); --> 获取并移除此一个元素;如果此列表为空,则返回 null。(1.6新特性)
总结:以上方法都来自于接口Quere,1.6新特性中的方法有特殊返回值。特殊返回值可以用来做判断标识。
补充:什么时候自动装箱?
基本类型值赋值给了对象引用的时候会自动装箱。
Set:一个不包含重复元素的 collection。
更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。无序的。
Set接口中的方法与Collection中的方法一致。
注意:Set取数只有一种方式:迭代器Iterator
|--HashSet 保证唯一的特点。该容器中不会有重复的对象。
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序.
内部结构数据为哈希表,是不同步的。
补充:哈希表-->实质还是数组
一般数组的存入都是以脚标来存入,查找的时候顺序对比,产生结果。
而哈希表在存入的时候会按照存入的对象的特性,存入指定的位置(无序的原因)
function(Element){ 一个算法,这个算法,对元素进行运算,并获取其位置。 注意:此算法就是hashcode();这个方法是由底层的windows做的,看不到。 我们可以做自己的算法:(简易原理实现:以字符串为例)另数组长度为10 即:0-9; 存放"ab"根据ab的asc值97+98=195 让195%10=5 ---->找到下标为5的位置进行比较,有就是有,没有就是没有。 ---->插入的时候,当有5存在的时候就不会插入(这就是为什么Set不会有对象重复的原因) ---->注意:并不能说明地址(下标)相同就是相同的内容(例如:"ba") ---->所以当地址(下标)相同的时候,再要比较内容。 return index; }
当要获取的时候再用一次该方法获取其位置,直接找到该元素。
总结哈希表:
哈希表确定元素是否相同
1.判断两个元素的哈希值是否相同。如果相同,进而比较两个对象的内容是否相同。
2.判断哈希值是否相同,其实判断的是对心的hashCode();的方法。
判断内容是否相同用的是equals();方法。
注意:如果哈希值不同,则不需要判断内容是否相同。
如果哈希值相同,但是内容不同(这种情况是很少的,因为哈希算法非常复杂,叫做哈希冲突),解决办法很多,可以顺延。
自定义对象的存储:(重点)
HashSet集合数据结构是哈希表,所以使用hashCode();方法来确定位置;如果位置相同,用equals();方法来确认内容是否相同。
如果不重写hashCode()方法,那么会调用父类(Object)的hashCode()方法。
如果不重写equals()方法,那么也会调用父类(Object)的equals()方法。父类的equals()方法比较的是地址,而没创建一个对象
肯定有一个新地址,所以equals()肯定不会相同,所以即便内容会相同,也会储存。
ArrayList和HashSet的区别:
ArrayList判断对象依赖的是equals();方法。
而HashSet判断对象用到的是hashCode();方法和equals();方法
所以当用ArrayList的remove()方法的时候,虽然对象的地址(下标)不同,但是只要内容相同,都会移除。
而HashSet就要用到hashCode()和equals()两个方法。
当我们想要保证对象唯一,并且还想要有序。在Set下面提供了一个实现类-->LinkedHashSet<E>
定义:
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。
链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)
理解:就是HashSet与链表相结合。
|--TreeSet
使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
即:要想对自定义对象排序,必须将该类实现Comparator类,并实现其方法:compareTo()。
int compareTo(Object o){ 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。 1、比较数值的时候,直接用逻辑符号>、<、=来判断。 2、比较字符串的时候,可以用public int compareTo(String anotherString)方法。 技巧:做差。 }
重要:判断元素唯一行的方法,就是根据比较方法的返回结果是否是0,如果是0,就是相同元素,不存。
总结:
TreeSet对元素进行排序的方式之一:
让元素自身具备比较功能,元素需要实现Comparator接口,并且覆盖compareTo()方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序怎么办?
可以使用TreeSet的第二种排序方式:
让集合自身具备排序功能。集合创建时就要有。即:构造方法。
创建一个比较器,实现Comparator接口。实现compare()方法:两两元素进行比较。
两种方式的区别:
第一种是利用元素自身的比较方法比,只需要传入一个元素即可。
第二种是利用集合自身的比较,要传入两个元素。
两个都存在的情况下面以构造器为主。实际开发用第二种比较多。
底层数据结构:
经典二叉树:当保存的时候使用二叉树保存,大的在右边,小的在左部。
int compare(Object o1,Object o2){ // 比较用来排序的两个参数。 根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。 如果指定返回一个正整数,则意味着存入的时候都往二叉树的右侧存,即有了一定的顺序:插入的顺序是怎么样的,查询的顺序就是怎么样的。 }
注意:只要不是按照自然排序就利用比较器
Map:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
与Collection区别:Map一次添加一对元素,Collection一次添加一个元素;Map也称为双列集合,Collection也称为单列集合。
根据定义:Map必须保证键的唯一性。
常用方法:
1、添加
V put(K key, V value):返回前一个key关联的值,如果没有返回null。
理解:如果该key之前没有对应的值,那么返回null,并且成功存入。如果key之前有值,那么返回之前的值(即把原来的值删除),并存入当前的值。
2、删除
void clear() 清空map集合
V remove(Object key):根据key值删除键值对
3、判断
boolean containsKey(Object key):有键吗?
boolean containsValue(Object value) :有值吗?
boolean isEmpty() :存在吗?
4、获取
V get(Object key) :通过键获取值。如果没有该键返回null。
int size() :返回键值对个数。
5、遍历
第一种:
Set<K> keySet() :得到所有键。-->既然是Set集合,那么就可以用迭代器迭代,为什么不反悔List?因为List不唯一。
第二种:
Set<Map.Entry<K,V>>entrySet(): 返回此映射中包含的映射关系的 Set 视图。(entry :登记)
原理:将键值对两个对象,封装成一个对象
补充:内部接口
Map接口下面有一个内部接口Entry
interface Map{
interface Entry{
public void get();
}
}
为什么要这么做?因为Entry是将键值对封装成一个对象,如果要用Entry那么前提肯定是Map,外部规则中有内部规则,内部规则访问外部规则的内容。
所以要写成内部接口的形式。
Collection<V> values() :为什么返回Collection?因为键虽然唯一,但是值不唯一。
常用子类:
|--Hashtable:内部数据结构哈希表,是同步的。表注:最早的双列集合 重点:不允许null作为键,不允许null作为值。
Properties:Properties 类表示了一个持久的属性集。用来存储键值对形式的配置文件。可以和I/O技术相结合才能发挥最大的水平。
|--HashMap:内部结构是哈希表,不是同步的。允许null作为键,允许null作为值。(与Hashtable的主要区别)
LinkedHashMap<K,V>:
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。
此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。
注意,如果在映射中重新插入 键,则插入顺序不受影响。
|--TreeMap:内部结构是二叉树,不同步,可以对Map集合中的键进行排序
注意:HashSet此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。
Map集合练习:
获取字符串中每个字符出现的次数。
Utilities:
工具类:便捷开发。
|--Collections
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
扩展:自定义排序方法
public static <T extends Comparable<? super T>> void MySort(List<T> list){
说明:<T extends Comparable<? super T>> 加限制,因为要保证调用该方法的集合可以比较。
}
补充:
Comparable接口与Comparator接口的区别:
Comparable 是排序接口。
若一个类实现了Comparable接口,就意味着“该类支持排序”。
即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);
那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序。
所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。
Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。
|--Arrays
此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。
除非特别注明,否则如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException。
注意:
数组转集合
static <T> List<T>asList(T... a) :返回一个受指定数组支持的固定大小的列表。
此方法同 Collection.toArray() 一起,充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
返回的列表是可序列化的,并且实现了 RandomAccess。
注意:
转换之后的List集合不能进行增删操作,因为数组为固定长度。
如果数组中的元素是对象,那么转成集合时,直接将【数组中的元素】作为集合中的元素进行存储。
如果数组中的元素是基本数据类型,那么在转成集合时,会将【数组】作为集合中元素进行存储。
因为集合中不能存储基本数据类型,所以在转型的时候,List的泛型要注意:之前数组怎么定义的,泛型就怎么写。
集合转数组
Collection接口中的Object[]toArray()和<T> T[] toArray(T[] a)方法。
集合转成数组,可以对集合中的元素进行限定,不允许增删。
补充:给非同步的集合加锁。
class MyCollections{
public List synList(List list){
return new MyList(list);
} class MyList implements List{
private List list;
private static final Object lock = new Object();
MyList(List list){
this.list = list;
}
public boolean add(Object obj){
synchronized(lock){
return list.add(obj);
}
}
public boolean remove(Object obj){
synchronized(lock){
return list.remove(obj);
}
}
...//实现其他方法并且都加锁。
}
}
Java集合框架学习笔记的更多相关文章
- JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue
前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...
- JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序
前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...
- Java集合框架学习(一)List
先附一张Java集合框架图. 从上面的集合框架图可以看到,Java集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射.Coll ...
- Java集合框架学习
集合框架 集合框架的目标 该框架必须是高性能的.基本集合(动态数组,链表,树,哈希表)的实现必须是高效的. 该框架允许 不同类型的集合,以类似的方式工作,具有高度的互操作性. 对一个集合的扩展和适应必 ...
- 【java基础 11】java集合框架学习
导读:本篇博客主要是从整体上了解java的集合框架,然后主要介绍几个自己在项目中用到的结构,比如说:hashtable.hashmap.hashset.arraylist等! 一.宏观预览 从宏观上看 ...
- java集合的学习笔记
不知不觉也到了java集合这一章的学习,这因该是挺重要的一个章节,因为所有的程序都离不开数据,而一个良好的数据结构和算法应该是程序的灵魂吧. 今天对自己所初步了解的做一个总结: 数据结构是计算机存储. ...
- JavaSE中Collection集合框架学习笔记(1)——具有索引的List
前言:因为最近要重新找工作,Collection(集合)是面试中出现频率非常高的基础考察点,所以好好恶补了一番. 复习过程中深感之前的学习不系统,而且不能再像刚毕业那样死背面试题,例如:String是 ...
- Java集合框架学习总结
转自:http://www.cnblogs.com/oubo/archive/2012/01/07/2394639.html Oubo的博客 以下介绍经常使用的集合类,这里不介绍集合类的使用方法,只介 ...
- 集合框架学习笔记<三>
一些重要的区别 set与list的区别: set是无索引的,list是有索引的: ArrayList与LinkList的区别: 前者是基于数组实现的,后者是基于链表实现的: 两者的使用方法一样,但是在 ...
随机推荐
- 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表中的标识列指定显式值
今天在处理数据时遇到这样一个错误 消息 8101,级别 16,状态 1,第 1 行 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'dbo.StockDetailValu ...
- oracle-12c-rac 报:ORA-01078
OS: Oracle Linux Server release 5.7 DB: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - ...
- Protocol Buffer使用
Protocol Buffer使用简介 字数2630 阅读5067 评论1 喜欢12 我们项目中使用protocol buffer来进行服务器和客户端的消息交互,服务器使用C++,所以本文主要描述pr ...
- iOS中的堆(heap)和栈(stack)的理解
操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...
- 有关UIView、subview的几个基础知识点-IOS开发 (实例)
环境是xcode4.3 首先要弄懂几个基本的概念. 一)三个结构体:CGPoint.CGSize.CGRect 1. CGPoint /* Points. */ struct CGPoint { C ...
- 关于htmlentities 、htmlspecialchars、addslashes的使用
1.html_entity_decode():把html实体转换为字符. Eg:$str = "just atest & 'learn to use '"; echo ht ...
- 关于const
1.顶层const和底层const const修饰的对象本身是常量,则为顶层const,否则为底层const 如: const int a=10; //a是int常量,顶层const i ...
- SAP如何使用关于序列号的表
- android 开发:讯飞的离线命令识别器官方demo使用及demo下载
场景:使用本地构建语法,离线识别命令词. 修改文件AsrDemo.java mLocalGrammar 修改为你自己的语法 mAsr.setParameter(SpeechConstant.GRAM ...
- html+css学习笔记 4[定位]
如何让图1中的div2移动到如图2上的位置: 思路:哪些css命令能够影响盒子显示的位置呢? relative相对定位/定位偏移量 position:relative; 相对定位 a ...