java集合复习转载

集合是

 

1,可以存储很多元素的容器

2,这个容器用于存储对象

3,而且该容器的长度是可变的

集合和数组的区别:

1,数组是固定长度的,集合是可变长度的

2,数组可以存引用类型和基本数据类型,如定义为 object数组,才可以存放任意数据类型。

集合只能存储引用数据类型,可存储不同类型的对象。

举例: 很多种的水杯,都可用来装液体,但内部的结构不一样。

教室:805教室转着圈装,315按排装。

1、集合框架体系

|--由来:数据多了可以用对象类存储,对象多了用集合来存。

|--概述:集合是一个容器、存储对象、长度可变化。

|--什么时候使用容器:一旦数据多了就得先把数据存储起来再操作,这样效率更好

|--和数组的区别:

1、数组定义时长度是固定的(必须明确元素类型和长度)集合定义时,可以不用明确长度,长度是可变的。

2、数组存储是同一类型的数据,集合存储的是对象,而对象可以是任意类型

3、数组可以存储基本数据值,而集合只能对象。

|--集合框架构成与分类:

|--数据结构?什么是数据结构?有哪些体现方式?

|--每一个容器因为自身的数据机构不同,进行了单独的描述和对象的封装,以为这些对象有共性就进行向上抽取,形成了集合框架,

|--学习体系结构的技巧:查阅顶层内容、建立低层对象(继承体系中学)

每一个容器的内部数据结构不同,就有了不同的容器。

API中的<E>:暂时先把E当成Object.这是1.5之后才有的,在1.4之前用的就是object.

Collection接口:java.util.Collection

Collection中常用的方法:

添加:add() 添加成功为真,不成功为假

addAll() 把一个集合添加到另外一个集合中

删除:remove() 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

removeAll()移除此 collection 中那些也包含在指定 collection中的所有元素(可选操作)。

clear() 清除容器中的所有元素,清除后返回空数组。

retainAll() 仅保留此 collection 中那些也包含在指定 collection的元素

判断:contains() 如果此 collection 包含指定的元素,则返回 true

containsAll() 如果此 collection 包含指定 collection中的所有元素,则返回 true

isEmpty() 是否为空

获取:size() 返回此 collection 中的元素数

iterator() 返回在此 collection 的元素上进行迭代的迭代器

转换:toArray() 返回包含此collection中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

具体方法,查API

Collection 层次结构 中的根接口。Collection表示一组对象,这些对象也称为 collection元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection是有序的,而另一些则是无序的。JDK不提供此接口的任何直接 实现:它提供更具体的子接口(如Set List)实现。此接口通常用来传递collection,并在需要最大普遍性的地方操作这些collection

add

boolean add(E e)

确保此 collection 包含指定的元素(可选操作)。如果此collection 由于调用而发生更改,则返回true。(如果此collection 不允许有重复元素,并且已经包含了指定的元素,则返回false。)

支持此操作的 collection 可以限制哪些元素能添加到此collection 中来。需要特别指出的是,一些collection 拒绝添加null 元素,其他一些collection 将对可以添加的元素类型强加限制。Collection类应该在其文档中清楚地指定能添加哪些元素方面的所有限制。

如果 collection 由于某些原因(已经包含该元素的原因除外)拒绝添加特定的元素,那么它必须 抛出一个异常(而不是返回false)。这确保了在此调用返回后,collection总是包含指定的元素。

参数:

e- 确定此 collection中是否存在的元素。

返回:

如果此 collection 由于调用而发生更改,则返回true

抛出:

UnsupportedOperationException-如果此 collection不支持 add操作

ClassCastException- 如果指定元素的类不允许它添加到此 collection

NullPointerException- 如果指定的元素为 null,并且此collection 不允许null 元素

IllegalArgumentException-如果元素的某属性不允许它添加到此 collection

IllegalStateException- 如果由于插入限制,元素不能在此时间添加

addAll

boolean addAll(Collection<? extendsE> c)

将指定 collection 中的所有元素都添加到此collection 中(可选操作)。如果在进行此操作的同时修改指定的collection,那么此操作行为是不确定的。(这意味着如果指定的collection 是此collection,并且此collection 为非空,那么此调用的行为是不确定的。)

参数:

c- 包含要添加到此 collection的元素的 collection

返回:

如果此 collection 由于调用而发生更改,则返回true

抛出:

UnsupportedOperationException-如果此 collection不支持 addAll方法

ClassCastException- 如果指定 collection 中某个元素的类不允许它添加到此collection

NullPointerException- 如果指定 collection 包含null 元素,并且此collection 不支持null 元素,或者指定的collection null

IllegalArgumentException-如果指定 collection的元素的某属性不允许它添加到此 collection

IllegalStateException- 如果由于插入限制,不是所有的元素都能在此时间添加

另请参见:

add(Object)

clear

void clear()

移除此 collection 中的所有元素(可选操作)。此方法返回后,除非抛出一个异常。

抛出:

UnsupportedOperationException-如果此 collection不支持 clear操作

equals

boolean equals(Object o)

比较此 collection 与指定对象是否相等。

Collection 接口没有对Object.equals 的常规协定添加任何约定时,直接实现该Collection 接口(换句话说,创建一个Collection,但它不是Set List 的类)的程序员选择重写Object.equals 方法时必须小心。没必要这样做,最简单的方案是依靠Object 的实现,然而实现者可能希望实现值比较,而不是默认的引用比较。(ListSet接口要求进行这样的值比较。)

Object.equals 方法的常规协定声称相等必须是对称的(换句话说,当且仅当存在b.equals(a) 时,才存在a.equals(b))。List.equalsSet.equals的协定声称列表只能与列表相等,set只能与 set相等。因此,对于一个既不实现 List又不实现 Set接口的 collection类,当将此 collection与任何列表或 set进行比较时,常规的 equals方法必须返回 false。(按照相同的逻辑,不可能编写一个同时正确实现Set List 接口的类。)

覆盖:

Object 中的equals

参数:

o- 要与此 collection进行相等性比较的对象。

返回:

如果指定对象与此 collection 相等,则返回true

另请参见:

Object.equals(Object), Set.equals(Object), List.equals(Object)

contains

boolean contains(Object o)

如果此 collection 包含指定的元素,则返回true。更确切地讲,当且仅当此collection 至少包含一个满足(o==null ? e==null : o.equals(e))的元素 e时,返回 true

参数:

o- 测试在此 collection中是否存在的元素。

返回:

如果此 collection 包含指定的元素,则返回true

抛出:

ClassCastException- 如果指定元素的类型与此 collection 不兼容(可选)。

NullPointerException- 如果指定的元素为 null,并且此collection 不允许null 元素(可选)。

containsAll

boolean containsAll(Collection<?> c)

如果此 collection 包含指定collection 中的所有元素,则返回true

参数:

c- 将检查是否包含在此 collection中的 collection

返回:

如果此 collection 包含指定collection 中的所有元素,则返回true

抛出:

ClassCastException- 如果指定 collection 中有一个或多个元素的类型与此collection 不兼容(可选)

NullPointerException- 如果指定 collection 包含一个或多个null 元素,并且此collection 不允许null 元素(可选),或者指定的collection null

另请参见:

contains(Object)

equals

boolean equals(Object o)

比较此 collection 与指定对象是否相等。

Collection 接口没有对Object.equals 的常规协定添加任何约定时,直接实现该Collection 接口(换句话说,创建一个Collection,但它不是Set List 的类)的程序员选择重写Object.equals 方法时必须小心。没必要这样做,最简单的方案是依靠Object 的实现,然而实现者可能希望实现值比较,而不是默认的引用比较。(ListSet接口要求进行这样的值比较。)

Object.equals 方法的常规协定声称相等必须是对称的(换句话说,当且仅当存在b.equals(a) 时,才存在a.equals(b))。List.equalsSet.equals的协定声称列表只能与列表相等,set只能与 set相等。因此,对于一个既不实现 List又不实现 Set接口的 collection类,当将此 collection与任何列表或 set进行比较时,常规的 equals方法必须返回 false。(按照相同的逻辑,不可能编写一个同时正确实现Set List 接口的类。)

覆盖:

Object 中的equals

参数:

o- 要与此 collection进行相等性比较的对象。

返回:

如果指定对象与此 collection 相等,则返回true

另请参见:

Object.equals(Object), Set.equals(Object), List.equals(Object)

hashCode

int hashCode()

返回此 collection 的哈希码值。当Collection 接口没有为Object.hashCode 方法的常规协定添加任何约束时,为了满足Object.hashCode 方法的常规协定,程序员应该注意任何重写Object.equals 方法的类必须重写Object.hashCode 方法。需要特别指出的是,c1.equals(c2)暗示着 c1.hashCode()==c2.hashCode()

覆盖:

Object 中的hashCode

返回:

collection 的哈希码值

另请参见:

Object.hashCode(), Object.equals(Object)

isEmpty

boolean isEmpty()

如果此 collection 不包含元素,则返回true

返回:

如果此 collection 不包含元素,则返回true

iterator

Iterator<E>iterator()

返回在此 collection 的元素上进行迭代的迭代器。关于元素返回的顺序没有任何保证(除非此collection 是某个能提供保证顺序的类实例)。

指定者:

接口 Iterable<E>中的 iterator

返回:

在此 collection 的元素上进行迭代的Iterator

remove

boolean remove(Object o)

从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。更确切地讲,如果此collection 包含一个或多个满足(o==null ? e==null : o.equals(e))的元素 e,则移除这样的元素。如果此collection 包含指定的元素(或者此collection 由于调用而发生更改),则返回true

参数:

o- 要从此 collection中移除的元素(如果存在)。

返回:

如果此调用将移除一个元素,则返回 true

抛出:

ClassCastException- 如果指定元素的类型与此 collection 不兼容(可选)

NullPointerException- 如果指定的元素为 null,并且此collection 不允许null 元素(可选)。

UnsupportedOperationException-如果此 collection不支持 remove操作

removeAll

boolean removeAll(Collection<?> c)

移除此 collection 中那些也包含在指定collection 中的所有元素(可选操作)。此调用返回后,collection中将不包含任何与指定 collection相同的元素。

参数:

c- 办好要从此 collection移除的元素的 collection

返回:

如果此 collection 由于调用而发生更改,则返回true

抛出:

UnsupportedOperationException-如果此 collection不支持 removeAll方法

ClassCastException- 如果此 collection 中一个或多个元素的类型与指定collection 不兼容(可选)

NullPointerException- 如果此 collection 包含一个或多个null 元素,并且指定的collection 不支持null 元素(可选),或者指定的collection null

另请参见:

remove(Object), contains(Object)

retainAll

boolean retainAll(Collection<?> c)

仅保留此 collection 中那些也包含在指定collection 的元素(可选操作)。换句话说,移除此collection 中未包含在指定collection 中的所有元素。

参数:

c- 包含保留在此 collection中的元素的 collection

返回:

如果此 collection 由于调用而发生更改,则返回true

抛出:

UnsupportedOperationException-如果此 collection不支持 retainAll操作

ClassCastException- 如果此 collection 中一个或多个元素的类型与指定collection 不兼容(可选)

NullPointerException- 如果此 collection 包含一个或多个null 元素,并且指定的collection 不允许null 元素(可选),或者指定的collection null

另请参见:

remove(Object), contains(Object)

size

int size()

返回此 collection 中的元素数。如果此collection 包含的元素大于Integer.MAX_VALUE,则返回Integer.MAX_VALUE

返回:

collection 中的元素数

toArray

Object[] toArray()

返回包含此 collection 中所有元素的数组。如果collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。

返回的数组将是安全的,因为此collection 并不维护对返回数组的任何引用。(换句话说,即使collection 受到数组的支持,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。

此方法充当了基于数组的 API 与基于collection API 之间的桥梁。

返回:

包含此 collection 中所有元素的数组

toArray

<T> T[] toArray(T[] a)

返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。如果指定的数组能容纳该collection,则返回包含此collection 元素的数组。否则,将分配一个具有指定数组的运行时类型和此collection 大小的新数组。

如果指定的数组能容纳 collection,并有剩余空间(即数组的元素比collection 的元素多),那么会将数组中紧接collection 尾部的元素设置为null。(只有 在调用者知道此collection 没有包含任何null 元素时才能用此方法确定collection 的长度。)

如果此 collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。

toArray() 方法一样,此方法充当基于数组的API 与基于collection API 之间的桥梁。更进一步说,此方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下,可以用来节省分配开销。

假定 x 是只包含字符串的一个已知collection。以下代码用来将collection 转储到一个新分配的String 数组:

String[] y = x.toArray(new String[0]);

注意,toArray(new Object[0]) toArray()在功能上是相同的。

参数:

a- 存储此 collection元素的数组(如果其足够大);否则,将为此分配一个具有相同运行时类型的新数组。

返回:

包含此 collection 中所有元素的数组

抛出:

ArrayStoreException- 如果指定数组的运行时类型不是此 collection 每个元素运行时类型的超类型

NullPointerException- 如果指定的数组为 null

下午讲的是迭代器 Iterator

什么是迭代器?如何使用?

使用前提:必须先有容器,因为是取容器中的数据。取出的元素不一样,动作也不相同。

Public interface Iterator<E>

collection进行迭代的迭代器。迭代器取代了Java Collections Framework 中的Enumeration。迭代器与枚举有两点不同:

· 迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。

· 方法名称得到了改进。

此接口是 Java Collections Framework 的成员。

从以下版本开始:

1.2

另请参见:

Collection, ListIterator,Enumerationr

Iterator 有三个方法:

hasNext

boolean hasNext()

如果仍有元素可以迭代,则返回 true。(换句话说,如果next 返回了元素而不是抛出异常,则返回true)。

返回:

如果迭代器具有多个元素,则返回 true

next

E next()

返回迭代的下一个元素。

返回:

迭代的下一个元素。

抛出:

NoSuchElementException-没有元素可以迭代。

remove

void remove()

从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的collection,则迭代器的行为是不确定的。

抛出:

UnsupportedOperationException-如果迭代器不支持 remove操作。

IllegalStateException- 如果尚未调用 next 方法,或者在上一次调用next 方法之后已经调用了remove 方法。

2、迭代器的设计原理以及思想:

其实就Collection这种集合的公共取出方式,因为每一个具体的容器的数据结构不同,它们的取出方式也是不一样的,要根据每一个容器的特点来定义特定的取出方式,而取出方式直接在访问容器中的元素,所以将取出方式定义在容器内部,是一个内部类,而对外提供Iterator接口,这样可以通过该接口访问任意collection容器中的元素,所以它的出现降低了耦合性,我们只要面对Iterator接口,使用iterator接口即可。

3、集合使用的细节:

1、直接存储基本数据类型值也是可以的,因为JDK1.5后有自动装箱,会将基本数据类型转成对象,JDK1.4绝对不行。Eg:coll.add(3)

2、集合对象中存储的其实是对象的元素的引用。

3、Add的参数是Object类型,可以接收所有的类型的对象,会出现向上转型,取出元素时类型还是Object不能使用具体对象的特有内容,想要使用特有内容向下转型。Eg:Object obj="obj";想要取出访问子类的特有方法,向下转型,String s=(String)it.next();sop(s.length());

5、collection框架体系:

Collection

|--list(列表):有序(存入的顺序和取出的顺序一致)因为该字体系中的元素有索引或者角标,所以是可以存储重复元素的。

|--list子体系中的特有方法:

1、增加:void add(index,element)

2、删除:Object removeindex

3、查找

4、修改:set(int index,element)返回值是当前被修改的对象

5、实现代码:

Public static void main(String[] args)

{

List list=new ArrayList();

methodDemo();

}

Public static void methodDemo(List list)

{

List.add("abc1");

List.add("abc2");

List.add("abc3");

List.add("abc4");

Sop(list);

//添加:

List.add(1,"abc7");//[abc1,abc7,abc2,abc3]在角标1位置往后顺延。

//删除

Object obj=list.remove(2);//删除指定索引上的元素,根据角标删除会返回来被删对象

Sop(obj);//obj:abc2 [abc1,abc7,abc3]

//获取:获取指定角标上的元素并返回,这也是和remove的区别。

Object obj=list.get(1);

Sop(obj);//obj:abc1 [abc1,abc7,abc3]

//获取元素的索引,如果元素存在返回索引,不存在返回-1,依次还可以判断元素是否存在。

Int index=list.indexOf("abc1");

Sop(index);//index=1

//获取指定的子列表sublist(fromIndex,toindex)包含头不包含尾

List=list.sublist(1,2);//[abc1]

//修改:

Object obj=list.set(1,"haha");

Sop(obj);//[abc1,haha,abc3]

记住:只有list集合支持增删改查。

}

}

6、listIterator:

列表迭代器:想要在迭代的过程中进行元素的增加等动作,iterator就不行了,可以使用其子接口listaIterator,而且该接口的对象只有通过list集合的listIterator方法获取,是List集合特有的取出元素方式,它包含了增删改查的方法,而iterator只有hasNext()next()remove()方法

实现代码:

Public static void main(String[] args)

{

List list=new ArrayList();

List.add("abc1");

List.add("abc2");

List.add("abc3");

List.add("abc4");

ListIterator it=list.listIterator();

While(it.hasNext())
{

Object obj=it.next();

If("abc2".equals(obj))

{

It.add("abc01");//添加元素

It.set("hehe");//修改元素

}

Else

{

Sop(obj);

}

}

}

Sop(it.hasNext());//false

iterator的区别:

实现代码:

Iterator it=list.iterator();//迭代器是集合的功能,知道集合中有多少元素。

While(it.hasNext())

{

Object obj=it.next();

//ConcurrentModificationException

多线程导致的,不能再同时遍历的时候进行删除,原因是迭代过程中,又使用集合对象对元素进行了操作导致了并发修改异常的发生,怎么去解决?迭代器的删除方式

If("abc2".equals(obj))

{

List.remove(obj);

It.remove();用迭代器的自身的方法。

}

Else
{

Sop(obj);

}

}

|--set:还没有学到!

6、list体系结构:

|--ArrayList:低层数据结构是数组,不同步,有别于vector,替代了它,也是可延长数组,百分之五十,提升了空间的效率。查询很快,增删很慢。

|--LinkedList:低层数据结构是链表数据结构,查询速度慢,增删比较快,元素也是有角标的,以为内其父类list都有角标。

|--Vector:低层数据结构是数组结构,超过长度就会创建一个新数组,长度为前数组 的一倍,对其进行重新赋值。同步 安全但是效率低。

|--特有方法:

Enumeration:枚举:支持枚举接口,但是该接口因为名称过长,被Iterator取代。

实现代码:

Public stati void main(String[] arsg)

{

Vector v=new Vector();

v.addElement("abc1");

v.addElement("abc2");

v.addElement("abc3");

v.addElement("abc4");

Enumeration en=v.elements();

While(en.hasNext())
{

Sop(en.nextElement());

}

}

注意:此接口和iteration接口的功能是重复的。

Arrrylistlinkedlist的内存分析比较:

总结:当增删操作较多时用linkedlist。当查询较多的时候用ArrayList,自有增删有查询的还是Arraylist,因为后面还是查询的使用较多。

——————————————————————————————————————————————————————————————————

 

1、LinkedList:

List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现List 接口外,LinkedList类还为在列表的开头及结尾 getremoveinsert元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列双端队列

此类实现 Deque 接口,为addpoll提供先进先出队列操作,以及其他堆栈和双端队列操作。

所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。

注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedList 方法来包装该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示:

List list = Collections.synchronizedList(new LinkedList(...));

特有方法:

增加:addFirst()

public void addFirst(E e)

将指定元素插入此列表的开头。

指定者:

接口 Deque<E>中的 addFirst

参数:

e- 要添加的元素

addLast()

public void addLast(E e)

将指定元素添加到此列表的结尾。

此方法等效于 add(E)

指定者:

接口 Deque<E>中的 addLast

参数:

e- 要添加的元素

JDk1.6之后出现了替代方法

Boolean offerFirst()

Boolean offerLast()

实现代码:

public static void main(String[] args){

LinkedList link=new LinkedList();

Link.addFirst("abc1");

Link.addFirst("abc2");

Link.addFirst("abc3");

Link.addFirst("abc4");

While(!link.isEmpty()){//此方法可以按照顺序取出元素,但是被删除,可以去模拟一些简单的数据结构

Sop(link.removeLast());//abc1abc2abc3abc4

}

}

扩展:堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了老的堆栈数据。 或者解释为 在长字符串中嵌入一段代码,并将过程的返回地址覆盖为这段代码的地址,这样当过程返回时,程序就转而开始执行这段自编的代码了。

重点:模拟堆栈、队列这两种常见的数据结构;

实现代码:队列:先进先出

public static void main(String[] args{

DuiLie d=new DuiLie();

d.myAdd("abc1");

d.myAdd("abc2");

d.myAdd("abc3");

While(!d.isNull()){//判断是否有元素

Sop(d.myGet());

}

}

class DuiLie

{

private LinkedList link;

DuiLie(){

link=new LinkedList();

}

提供添加元素的方法

public void myAdd(Object obj)

{

link.addFirst(obj);//这里修改为link.addLast()就是堆栈

}

提供获取元素的方法

public Object myGet(){

return link.removeLast();

}

判断集合中是否有内容

Public boolean isNull(){

Return link.isEmpty();

}

}

获取:Object getFirst()获取对象,不删除,如果集合中没有元素会抛出NoSuchElementException;

Object getLast();

JDK1.6

Object peekFirst()

Object peeklast()

1、获取对象:

Object removeFirst()获取到元素,但是删除了。

Object removeLast();

Object pollFirst()

Object pollLasrt()

removeFirst

public E removeFirst()

移除并返回此列表的第一个元素。

指定者:

接口 Deque<E>中的 removeFirst

返回:

此列表的第一个元素

抛出:

NoSuchElementException-如果此列表为空

removeLast

public E removeLast()

移除并返回此列表的最后一个元素。

指定者:

接口 Deque<E>中的 removeLast

返回:

此列表的最后一个元素

抛出:

NoSuchElementException-如果此列表为空

pollFirst

public E pollFirst()

获取并移除此列表的第一个元素;如果此列表为空,则返回 null

指定者:

接口 Deque<E>中的 pollFirst

返回:

此列表的第一个元素;如果此列表为空,则返回 null

从以下版本开始:

1.6

pollLast

public E pollLast()

获取并移除此列表的最后一个元素;如果此列表为空,则返回 null

指定者:

接口 Deque<E>中的 pollLast

返回:

此列表的最后一个元素;如果此列表为空,则返回 null

从以下版本开始:

1.6

2、Set集合:无序、不重复、该接口中的方法和Collection接口中的方法一致。

一个不包含重复元素的 collection。更确切地讲,set不包含满足 e1.equals(e2) 的元素对e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

|--HashSet底层哈希表数据结构,不同步的,它保证元素唯一性的方式:

根据元素的两个方法来完成的,一个是hashCode、一个equals。只有当hashCode方法算出的哈希值相同时,会再次判断两个元素的equals方法是否为ture

如果是true说明两个元素相同,不存储,所以往hashSet集合中存储自定义对象时,要覆盖hashCodeequals方法,通过自定义独享具备的特有数据来定义hashCodeequals的具体实现。

此类实现 Set 接口,由哈希表(实际上是一个HashMap 实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null 元素。

此类为基本操作提供了稳定性能,这些基本操作包括 addremovecontainssize,假定哈希函数将这些元素正确地分布在桶中。对此set 进行迭代所需的时间与HashSet 实例的大小(元素的数量)和底层HashMap 实例(桶的数量)的容量的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

注意,此实现不是同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用Collections.synchronizedSet 方法来包装” set。最好在创建时完成这一操作,以防止对该set 进行意外的不同步访问:

Set s = Collections.synchronizedSet(new HashSet(...));

哈希结构表分析:

Hash表和数组表的比较,哈希表数据结构是按照元素的特征通过指定的功能算出该元素的位置,这种方式查找时候比较快,不 用去遍历整个数组,直接用要查找的数据进行元素即可,存入其他的数据类型也可以,比如说字符串,只要定义一个功能算法对其进行运算即可,

注意:哈希值冲突,比如31%1021%10最后的值都是1,只是往1角标中存储就冲突了,怎么去解决这个问题呢?哈希表有种特殊的方式:再散列方式(就是再把这个数据进行取模,算出其他的位置),除此之外还有另外一种方式:当算到相同的值时,就在该冲突的位置的基础上向下顺延一个位置出来,这时候便不再冲突了,如过还有值冲突就继续向下顺延,上图结构通过equals方法来判断对象是否想用,这个方法只有在哈希值一样的时候才会用到。

实现代码:

需求:存储自定义对象,比如Person,同姓名和同年龄视为同一个人,是相同元素。

hashSet hs=new hashSet();

Hs..add(new Person("lisi1",20));

Hs..add(new Person("zhangsan",20));

Hs..add(new Person("wangwu",20));//addnull,返回true

Hs..add(new Person("sunba",20));

Hs..add(new Person("zhangsan",20));

取出来

Iterator it=hs.iterator();//对 collection 进行迭代的迭代器

While(it.hasNext())//hasNext()是否有下一个元素

{

Person p=(Person)it.next();

Sop(p.getName()+p.getAge());

}

class Person()

{

private String name;

private int age;

Person(String name,int age)

{

this.name=name;

this.age=age;

}

public void setName(String name){

this.name=name;

}

public void getName()

{

return name;

}

public void setAge(){

this.age=age;

}

public int getAge()
{

return age;

}

public String toString(){

return "Person:"+name+"::"+age;

}

定义一个比较方式,按照年龄进行自然排序

public int compareTo(Object o){

Person p=(Person)o;

int temp=this.age-p.age;

return temp==0?this.name.compareTo(p.name):temp;

/**按照姓名进行自然排序

int temp=this.name.compareTo(p.name){

return temp=-0?this,.age-p.age:temp;

}

*/

}

覆盖hashCode()方法

public int hashCode(){

final int NUMBER=28;//为什么要定义常量,是因为避免哈希值冲突的情况,比如说一个姓名取哈希值为20,年龄取哈希值为40.另外一个人的姓名取哈希值为40年龄哈希值为20;两个的和都是60,用它进行哈希运算,可能得到的值都是相同的,这样的话在哈希结构表中的数据存储都是冲突的。所以才定义这样一个常量类避免这种冲突。

return name.hashCode()+age*NUMBER;

}

覆写equals方法其实就是建立对象自身特有的判断对象是否相同的依据。

public boolean equals(Object o){

if(!(Obj instanceof Person))

throw new ClassCastException("数据错误"):

Person p=(Person)obj;

return this.name.equals(p.name)&&this.age==p.age;

}

}

|--TreeSet用于给Set集合中的元素按照指定的顺序进行排序,底层是二叉树数据结构,线程是不同步的。

如何保证元素的唯一性呢?就是用元素对象的比较方法返回值来确定的,如果为0,视为两个元素为相同的元素,不存储。

两种排序方式:

1、让元素自身具备比较功能,就是强制让元素去实现comparable接口,覆盖compareTo方法。这时元素具备的自然排序。可是如果元素自身不具备比较的功能,获取具备的比较功能不是所需要的。这时该排序方式就不能用了。

2、让集合自身具备比较功能,需要定义比较器,其实就是将实现了Comparator接口的子类对象作为参数传递给TreeSet集合的构造函数,让TreeSet集合一创建就具备了比较功能。该子类必须要覆盖compare方法。

二叉树数据结构分析:

二叉树数据结构的特点,当第一个元素存入时,后面存入的数据都要跟它进行比较,如果小则存储在这个元素的左边的位置,如果大就存储在这个元素的右边的位置,依次下去,它在对元素进行遍历的时候,不是从上到下,而是跟你要遍历的元素与它进行比较。

实现代码:

TreeSet ts=new TreeSet(new ComparatorByName());

Ts.add(new Person("lisia",29));

Ts.add(new Person("lisic",30));

Ts.add(new Person("lisiz",21));

Ts.add(new Person("lisi11",41));

Iterator it=ts.iterator();

while(it.hasNext()){

Person p=(Person)it.next();

Sop(p.getName()+p.getAge());

}

当元素自身没有比较功能的时候要定义实现Comparator接口的方法,让对象具备有比较功能,这时候要覆盖comparator接口的compare方法

实现代码:

class comparatorByName implementscomparator{

public int compare(Object o1,Object O2){

Person p1=Person)o1;

Person p2=(Person)o2;

int temp=p1.getName().compareTo(p2.getName());

return temp==0?p1.getAge()-p2.getAge():temp;

}

}

3、查阅集合的技巧

List

|--Vector

|--ArrayList

|--LinkedList

Set

|--HashSet
|--TreeSet

JDk1.2集合框架出现后,名称的阅读性非常强,通过名称就可以识别。明确所属的子体系,只要看后缀名,到底具体这个集合是什么结构,有什么特点,只要看前缀即可。

看到Array:数组结构,就要想到角标,有序,可重复,查询快

看到link:链表结构,想到增删快,同时可以明确操作first last的方法

看到hash:哈希表结构,就要想到无序,不可以重复,必须要想到元素依靠的hashCodeequals方法来保证唯一性。

看到Tree:二叉树,就要想到比较的功能和排序,必须要想到两个接口,Comparable--compareTo Comparator---compare

集合中常用的集合对象都是不同步的。

4、泛型:

1、由来:

jdk1.4版本之前,定义容器可以存储任意类型的对象,但是取出时,如果使用了具体元素的方法,需要向下转型的动作,因为元素类型的不一致,会导致运行时类型转换异常。

原因是:在定义集合时,并没有明确集合中的元素的具体类型,借鉴数组的定义方式就可以避免这个问题。

JDk1.5版本以后出现了一个解决机制,忽悠事故在定义容器时,直接明确容器中的元素的类型,这既是泛型的表现,用<>格式来使用。

其实泛型就是使用到了带有<.>的类和接口时,传递需要操作的对象类型就可,其实就是传递类型参数。

2、什么时候写泛型?

最简单的而一种体现,只要使用了带有<>的类和接口,就指定具体对象类型、

3、泛型的好处:

1、将运行时出现的类型转换异常问题在编译时期给解决了,运行就安全了.

2、避免了强制转换的麻烦.

所以泛型就是JDK1.5后出现一个安全机制。

泛型擦除:

泛型是编译时期的安全机制,编译时通过泛型机制,编译器多了对元素类型进行检查的步骤,如果检查通过,差生的class文件是不带有泛型的。

泛型补偿:

在对元素存储的时候,可以完成类型的判断,怎么用指定的类型来接收呢?JVM在运行时,会获取元素的类型,并用该类型对元素进行转换即可。

java.util
Vector<E>

Java 2 平台v1.2 开始,此类改进为可以实现List 接口,使它成为Java Collections Framework 的成员。与新collection 实现不同,Vector 是同步的。

Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建Vector 后进行添加或移除项的操作。

java.util
类 LinkedList<E>

List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现List 接口外,LinkedList类还为在列表的开头及结尾 getremoveinsert元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列双端队列

此类实现 Deque 接口,为addpoll提供先进先出队列操作,以及其他堆栈和双端队列操作。

此例不是同步的

get(int index)
返回此列表中指定位置处的元素。

getFirst()
返回此列表的第一个元素。

getLast()
返回此列表的最后一个元素。

offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。

offerFirst(E e)
在此列表的开头插入指定的元素。

offerLast(E e)
在此列表末尾插入指定的元素。

peek()
获取但不移除此列表的头(第一个元素)。

peekFirst()
获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。

peekLast()
获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。

poll()
获取并移除此列表的头(第一个元素)

pollFirst()
获取并移除此列表的第一个元素;如果此列表为空,则返回 null。

pollLast()
获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。

java.util
ArrayList<E>

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector 类,除了此类是不同步的。)

sizeisEmptygetsetiteratorlistIterator操作都以固定时间运行。add操作以分摊的固定时间 运行,也就是说,添加n 个元素需要O(n) 时间。其他所有操作都以线性时间运行(大体上讲)。与用于LinkedList 实现的常数因子相比,此实现的常数因子较低。

每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。

注意,此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步

ensureCapacity(int minCapacity)
如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。

removeRange(int fromIndex, int toIndex)
移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。

trimToSize()
将此 ArrayList 实例的容量调整为列表的当前大小。

toArray(T[] a)
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

toArray()
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。

java.util
HashSet<E>

此类实现 Set 接口,由哈希表(实际上是一个HashMap 实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null 元素。

此类为基本操作提供了稳定性能,这些基本操作包括 addremovecontainssize,假定哈希函数将这些元素正确地分布在桶中。对此set 进行迭代所需的时间与HashSet 实例的大小(元素的数量)和底层HashMap 实例(桶的数量)的容量的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

注意,此实现不是同步的。只有八个方法

add(E e)
如果此 set 中尚未包含指定元素,则添加指定元素。

clear()
从此 set 中移除所有元素。

clone()
返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。

contains(Object o)
如果此 set 包含指定元素,则返回true

isEmpty()
如果此 set 不包含任何元素,则返回true


iterator()
返回对此 set 中元素进行迭代的迭代器。

remove(Object o)
如果指定元素存在于此 set 中,则将其移除

size()
返回此 set 中的元素的数量(set的容量)。

java.util
TreeSet<E>

基于 TreeMapNavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建set 时提供的Comparator 进行排序,具体取决于使用的构造方法。

此实现为基本操作(addremovecontains)提供受保证的log(n) 时间开销。

注意,如果要正确实现 Set 接口,则set 维护的顺序(无论是否提供了显式比较器)必须equals 一致。(关于与equals 一致 的精确定义,请参阅Comparable Comparator。)这是因为Set 接口是按照equals 操作定义的,但TreeSet 实例使用它的compareTo(或compare)方法对所有元素进行比较,因此从set 的观点来看,此方法认为相等的两个元素就是相等的。即使set 的顺序与equals 不一致,其行为也是 定义良好的;它只是违背了Set 接口的常规协定。

注意,此实现不是同步的。

tailSet(E fromElement, boolean inclusive)
返回此 set 的部分视图,其元素大于(或等于,如果inclusive 为 truefromElement。


pollLast()
获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。

pollFirst()
获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。-------

——————————————————————————————————————————————————————————————————

集合:
1,是可以存储很多元素的容器。
2,这个容器用于存储对象。
3,而且该容器的长度是可变的。
集合和数组的区别:
1,
数组是固定长度,
集合是可变长度。
2,
数组可以存储引用类型,也可以存储基本类型。
集合只能存储引用类型。

--------
集合框架的由来:
集合有很多种,因为每一个集合中的数据结构(数据在容器中存取的具体的方式)都不一样。
但都具备共性功能,就不断地向上抽取。就形成了集合框架。该框架的顶层Collection接口。

学习框架原则:看顶层,用底层。
了解一下api中的Collection中的共性方法。
演示Collection中的共性方法:
1,添加。
add(Object)
addAll(collection)
2,删除:
remove(object)
removeAll(collection)
clear();
retainAll(collection);
3,判断:
contains(object)
containsAll(collection)
isEmpty();
4,获取:
size();
iterartor();获取迭代器。每一个集合都具备。
5,转换
toArray(); 将集合转成数组。

------------

迭代器的使用:
for(Iterator it = collection.iterator(); it.hasNext() ; ){
System.out.println(it.next());
}

迭代器:是容器中的一个内部类,因为该类要直接访问容器中的元素。
同时对外提供了公共的访问规则Iterator接口。
这样的好处,不需要知道具体的容器,只要是Collection中的容器
都可以通过该种取出方法取出体系中的所有容器中的元素。
降低了具体容器和取出方式的耦合性。
想要获取集合中的迭代器对象,就可以通过iterator方法来完成。

---------------
Collection
|--List:有序的(存入的顺序和取出的顺序保持一致),该集合中的元素都有索引,可以有重复元素。

|--Set:不允许有重复元素,元素不保证有序。

List:特有方法:都是围绕的索引展开的。
1,添加:
add(index,element);
add(index,collection);
2,获取
get(index):通过角标获取元素。
indexOf(object);
lastIndexOf(object);
subList(fromindex,toindex);
3,删除
remove(index):通过角标删除元素,并返回被删除的元素。
4,修改
set(index,element);
List具备着对容器中的元素进行增删改查的功能。只有该集合有。
为啥呢?因为索引。

5,特有的迭代器。ListIterator。可以在迭代时进行元素的增删改查。

------------
List
|--Vector:底层数据结构是一个数组。 而且数组可以增长。其实数组增长的原理:存储元素时,超出数组角标,
会创建新数组,将原数组的数据复制到新数组中,并将新元素存储到新数组中。
它是同步的。效率非常低。
|--ArrayList:底层数据结构也是可变长度的数组,是不同步的,比Vector效率高。查询元素的速度很快。
|--LinkedList:底层数据结构是链表数据结构,是不同步的。对元素的增删操作很快。

-----------
Set:方法都是来自于Collection。
|--HashSet:数据结构是哈希表,是不同步的。

|--TreeSet:数据结构是二叉树结构。是不同步的。可以对Set集合中的元素进行指定方式的排序。默认用的元素的自然排序。
TreeSet判断元素唯一性的方式,是比较方法的返回值是否为0.如果是0,视为元素相同,不存。

排序方式有两种:
1,让元素自身具备比较性,该元素需要实现Comparable接口,覆盖compareTo方法。
让元素具备了自然排序。
该种方式有弊端,如果元素自身具备的自然排序不是所需要的,怎么办?
还有,万一元素根本就不具备自然排序怎么办?

2,可以让容器自身具备比较性,而且应该添加元素之前,所以应该在容器对象创建时,就必须明确比较性。
那就应该参考该容器的构造函数。发现可以指定一个比较器,定义一个Comparator接口的子类,并覆盖compare方法。
将Comparator接口的子类对象作为参数传递给TreeSet集合的构造函数。




-----------------

Collection集合的子类对象阅读技巧。
具体的容器是什么结构?是否是同步?
通过名称就可以获得。容器的前缀名是数据结构的名字。后缀名是所属体系的名字。
凡是后缀名是体系名的集合,通常都是不同步的。
ArrayList:数据结构是数组。所属于List体系。
看到数组必须想到索引,必须要知道查询速度快。

LinkedList:数据结构是链表,看到链表就要想到,增删速度快,而且要接的 add,get,remove的first last方法。

HashSet:数据结构是哈希表,看到哈希就必须想到对元素进行hashCode和equals方法的复写。
TreeSet:数据结构是二叉树,看到树,就要想到比较排序,就要想到两个接口,Comparable Comparator。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值