正在学习Java?
想要对Java数据结构有更多了解?
下拉阅读这份《Java精华笔记之数据结构》,纯干货!
Java精华笔记之数据结构
牛客用户:IT、小农民
大家应该熟悉使用java.util包里面的各种数据结构,常用的数据结构有线性表、链表、哈希表等,在我们进行java开发时,JDK已经给我们提供了一系列的相应类来实现基本的数据结构。
常用集合类的继承结构如下:
Collction
├List
│├LinkdList
│├ArrayList
│└Vctor
│ └Stack
└St
Map
├Hashtabl
├HashMap
└WakHashMap
Collction是最近本的集合接口,一个Collction代表一组Objct(Elmnts)。java的SDK不提供直接继承Collction的类,而是继承Collction的子接口如:List、St。
这里Collction、List、St和Map都是接口(Intrfac),不是具体的实现类。根据上图可以直到List实现类有ArrayList和LiskdList和Vctor。
Collction元素如何遍历?不论Collction的实际类型是什么,它都支持一个itrator()的方法,返回一个迭代子,是该迭代子可以逐一访问Collction中每一个元素。代码如下:
Itratorit=c.itrator();//获取一个迭代子 whil(it.hasNxt()){ Objctobj=it.nxt();//获取下一个元素 Systm.out.println(obj);}
由Collction接口派生的两个接口是List和St。
主要方法:
List接口
List是有序的Collction,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的St不同,List允许有相同的元素。
除了具有Collction接口必备的itrator()方法外,List还提供一个listItrator()方法,返回一个ListItrator接口,和标准的Itrator接口相比,ListItrator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。
实现List接口的常用类有LinkdList,ArrayList,Vctor和Stack。
主要方法:
voidadd(intindx,Objctlmnt)在指定位置上添加一个对象
boolanaddAll(intindx,Collctionc)将集合c的元素添加到指定的位置
Objctgt(intindx)返回List中指定位置的元素
intindxOf(Objcto)返回第一个出现元素o的位置.
Objctrmovint(intindx)删除指定位置的元素
Objctst(intindx,Objctlmnt)用元素lmnt取代位置indx上的元素,返回被取代的元素
LinkdList类
LinkdList实现了List接口,允许null元素。此外LinkdList提供额外的gt,rmov,insrt方法在LinkdList的首部或尾部。这些操作使LinkdList可被用作堆栈(stack),队列(quu)或双向队列(dqu)。
注意LinkdList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
Listlist=Collctions.synchronizdList(nwLinkdList(...));
ArrayList类
ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
siz,isEmpty,gt,st方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用nsurCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkdList一样,ArrayList也是非同步的(unsynchronizd)。
主要方法:
Boolanadd(Objcto)将指定元素添加到列表的末尾
Boolanadd(intindx,Objctlmnt)在列表中指定位置加入指定元素
BoolanaddAll(Collctionc)将指定集合添加到列表末尾
BoolanaddAll(intindx,Collctionc)在列表中指定位置加入指定集合
Boolanclar()删除列表中所有元素
Boolanclon()返回该列表实例的一个拷贝
Boolancontains(Objcto)判断列表中是否包含元素
BoolannsurCapacity(intm)增加列表的容量,如果必须,该列表能够容纳m个元素
Objctgt(intindx)返回列表中指定位置的元素
IntindxOf(Objctlm)在列表中查找指定元素的下标
Intsiz()返回当前列表的元素个数
Vctor类
Vctor非常类似ArrayList,但是Vctor是同步的。由Vctor创建的Itrator,虽然和ArrayList创建的Itrator是同一接口,但是,因为Vctor是同步的,当一个Itrator被创建而且正在被使用,另一个线程改变了Vctor的状态(例如,添加或删除了一些元素),这时调用Itrator的方法时将抛出ConcurrntModificationExcption,因此必须捕获该异常。
Stack类
Stack继承自Vctor,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vctor得以被当作堆栈使用。基本的push和pop方法,还有pk方法得到栈顶的元素,mpty方法测试堆栈是否为空,sarch方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。
St接口
St是一种不包含重复的元素的Collction,即任意的两个元素1和2都有1.quals(2)=fals,St最多有一个null元素。
很明显,St的构造函数有一个约束条件,传入的Collction参数不能包含重复的元素。
请注意:必须小心操作可变对象(MutablObjct)。如果一个St中的可变元素改变了自身状态导致Objct.quals(Objct)=tru将导致一些问题。
Map接口
请注意,Map没有继承Collction接口,Map提供ky到valu的映射。一个Map中不能包含相同的ky,每个ky只能映射一个valu。Map接口提供3种集合的视图,Map的内容可以被当作一组ky集合,一组valu集合,或者一组ky-valu映射。
主要方法:
boolanquals(Objcto)比较对象
boolanrmov(Objcto)删除一个对象
put(Objctky,Objctvalu)添加ky和valu
Hashtabl类
Hashtabl继承Map接口,实现一个ky-valu映射的哈希表。任何非空(non-null)的对象都可作为ky或者valu。
添加数据使用put(ky,valu),取出数据使用gt(ky),这两个基本操作的时间开销为常数。
Hashtabl通过initialcapacity和loadfactor两个参数调整性能。通常缺省的loadfactor0.75较好地实现了时间和空间的均衡。增大loadfactor可以节省空间但相应的查找时间将增大,这会影响像gt和put这样的操作。
使用Hashtabl的简单示例如下,将1,2,3放到Hashtabl中,他们的ky分别是”on”,”two”,”thr”:
Hashtablnumbrs=nwHashtabl(); numbrs.put(“on”,nwIntgr(1)); numbrs.put(“two”,nwIntgr(2)); numbrs.put(“thr”,nwIntgr(3));
要取出一个数,比如2,用相应的ky:
Intgrn=(Intgr)numbrs.gt(“two”); Systm.out.println(“two=”+n);
由于作为ky的对象将通过计算其散列函数来确定与之对应的valu的位置,因此任何作为ky的对象都必须实现hashCod和quals方法。hashCod和quals方法继承自根类Objct,如果你用自定义的类当作ky的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.quals(obj2)=tru,则它们的hashCod必须相同,但如果两个对象不同,则它们的hashCod不一定不同,如果两个不同对象的hashCod相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCod()方法,能加快哈希表的操作。
如果相同的对象有不同的hashCod,对哈希表的操作会出现意想不到的结果(期待的gt方法返回null),要避免这种问题,只需要牢记一条:要同时复写quals方法和hashCod方法,而不要只写其中一个。
Hashtabl是同步的。
HashMap类
HashMap和Hashtabl类似,不同之处在于HashMap是非同步的,并且允许null,即nullvalu和nullky。,但是将HashMap视为Collction时(valus()方法可返回Collction),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者loadfactor过低。
WakHashMap类
WakHashMap是一种改进的HashMap,它对ky实行“弱引用”,如果一个ky不再被外部所引用,那么该ky可以被GC回收。
Collctions和Arrays
java集合中里面有两个类为Collcitons和Arrays,这是JCF(JavaCollctionsFramwork)里面功能强大的工具。提供的算法如下:
binarySarch:折半查找。
sort:排序,只是一种类似快速排序的方法,效率仍然是O(n*logn),但是一种稳定的排序方法。
rvs:线性表进行逆序操作。
rotat:以摸个元素为轴心将线性表“旋转”。
swap:交换一个线性表中的2个元素位置。
Collctions还有一个重要功能就是“封装器”(Wrappr),它提供了一些方法可以把一个集合转换成一个特殊的集合,如下:
unmodifiablXXX:转换成只读集合,这里XXX代表六种基本集合接口:Collction、List、Map、St、SortdMap和SortdSt。如果你对只读集合进行插入删除操作,将会抛出UnsupportdOprationExcption异常。synchronizdXXX:转换成同步集合。singlton:创建一个仅有一个元素的集合,这里singlton生成的是单元素St,singltonList和singltonMap分别生成单元素的List和Map。空集:由Collctions的静态属性EMPTY_SET、EMPTY_LIST和EMPTY_MAP表示。
总结
1、ArrayList:元素单个,效率高,多用于查询2、Vctor:元素单个,线程安全,多用于查询3、LinkdList:元素单个,多用于插入和删除
4、HashMap:元素成对,元素可为空
5、HashTabl:元素成对,线程安全,元素不可为空
如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkdList,如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
要特别注意对哈希表的操作,作为ky的对象要正确复写quals和hashCod方法。
▼点击阅读原文获得实用干货
看白癜风的医院哪个好白癜风治疗中心