您的位置:首页 > 职场人生

黑马程序员—java基础之集合

2013-06-05 00:56 225 查看

黑马程序员—java基础之集合

------- android培训java培训、期待与您交流!
----------

感恩,感恩,感恩!懂得感恩的人,才会是有福报的人!感谢所有发生的一切!

什么是集合:集合是一个容器. 还记得数组也是一个容器,那么他们之间有什么不同呢.

集合与数组比较

数组有什么特点?

1.有顺序

2.定长

3.类型单一

集合特点:

1.有顺序也可以没顺序

2.集合长度可以随着元素的增加而增加

3.集合中可以装入任何Object

Java中的集合类都在java.util包下

Java中的集合元素全是Object类型的。

Collection集合

Collection(特点:有顺序也无顺序,可重复也不可重复)

它是一个接口,下面是它的子接口.

|---List:有顺序的可重复

|----ArrayList

|----LinkedList

|----Vector

|---Set :无顺序不可重复

|-----HashSet

|-----TreeSet

重复的概念是两个元素做equals相等

Collection接口中声明的方法

1.add 向集合中添加元素

声明:public boolean add(Object obj)

作用:向集合添加元素obj

参数:要添加的元素

返回值:代表是否添加成功.

2.clear清空集合中的元素

声明:public void clear();

作用:清空集合中所有元素

3.contains判断集合中是否包含指定元素

声明:public boolean contains(Object obj)

作用:判断集合中是否包含指定元素,如果包含返回true,不包含返回false;

注意:所谓的包含是指obj与集合中的元素做equals返回true.

4.size

声明:public int size();

作用:返回集合中元素的个数

5.isEmpty

声明:public boolean isEmpty();

作用:判断集合中是否包含元素,如果没有任何元素返回true,有元素返回false

6.remove

声明:public boolean remove(Object obj)

作用:删除集合中的指定元素obj,如果删除成功返回true,否则返回false

注意:一次只能删除一个.

Collection中的所有带All方法

1.addAll

声明:public boolena addAll(Collection c);

作用:求两个集合的并集

简单说就是将两个集合中内容合并

2.containsAll

声明:public boolean containsAll(Collection c)

作用:判断集合c是否是集合的子集

3.removeAll

声明:public boolean removeAll(Collection c);

作用:将集合中包含的c集合中的所有元素删除。如果一个都不包含,返回false;

4.retainAll

声明:public boolean retainAll(Collection c);

作用:得到两个集合的交集.

Collection中的迭代器(****)

想要将集合中的所有元素取出来,需要使用迭代器.

声明:public Iterator iterator();

Iterator它是对Collection进行迭代的迭代器(简单说就是用来遍历 Collection集合的)

Iterator接口中的方法

1.hasNext

声明:public boolean hasNext();

作用:判断集合中是否有元素可以进行迭代

2.next

声明:public Object next();

作用:将下一个迭代出来。

3.remove

声明

publicvoid remvoe();

作用: 删除元素

使用迭代器遍历集合元素步骤

1.创建迭代器

Iteratorit=集合对象.iterator();

2.通过迭代器判断是否有元素可以进行迭代

while(it.hasNext()){它返回的是boolean 值

}

3.通过迭代器将元素迭代出来

Objectobj=it.next();

集合中的元素在迭代出来后,都是Obejct

关于迭代器的问题

iterator这个方法是声明在Collection接口中.

Iteratorit=集合对象.iterator();

在迭代的过程中不能对集合中元素进行修改,如果修改产生java.util.ConcurrentModificationException

关于迭代器中的remove方法与Collection中的方法区别

在对集合使用迭代器操作的过程中,不允许使用集合提供的可以修改集合中元素的方法。

例如:将集合中的元素删除,如果想要删除,必须使用迭代器提供的行为.

迭代器的实现伪代码

interfaceIterator{

}

interfaceCollection{

Iteratoriterator();

}

classArrayList implements Collection{

publicIterator iterator(){

returnnew Iter();

}

class Iter implements Iterator{

}

}

classLinkedList implements Collection{

publicIterator iterator(){

returnnew LinkedIter();

}

classLinkedIter implements Iterator

{

}

}

Collection c=new ArrayList();

Iteratorit=c.iterator();

List集合

List集合的特点:有顺序可重复

List是继承自Collection,Collection中的方法在List中都是存在。

List集合是有索引的,我们可以通过索引对其元素进行精确控制.

List集合中的特性方法:

1.add方法

声明:public void add(int index,Object obj);

作用:在指定index索引位置添加元素

2.get方法(***)

声明:public Object get(int index);

作用:根据索引index得到对应位置上的元素

3.remove方法

声明:public Object remove(int index);

作用:将指定index索引位置上的元素删除,返回值就是删除的元素.

4.set方法

声明:public Object set(int index,Object obj)

作用:使用obj将index位置上的元素替换,返回值是被替换的元素.

List集合的遍历方式

1.通用方式 Iterator(适用于所有的Collection集合)

通过从Collection继承的iterator方法

2.使用get(只适用于List集合)

因为List集合是有顺序的,我们可以通过索引对其位置上进行控制

3.使用List集合的特有的迭代器械 ListIterator(只适用于List集合)

ListIterator是继承自Iterator,也就是在Iterator中声明的hasNext,next,remove方法它也有。

但是它还提供了特有的方法

add

set

ListIterator比Iterator功能增强

1.Iterator只能从上到下遍历,而ListIterator可以双向遍历

2.Iterator在迭代过程中不能修改,而ListIterator可以add ,set

ArrayList

它实现了List集合,所以在List集合中的方法它都可以用

我们主要研究,ArrayList的实现方式

ArrayList它的实现是使用可变数组

ArrayList类的特点:

1.它的底层实现是使用数组实现。

2.每一次数组会扩充50%

3.它是线程不安全。在单线程中使用。

//扩充方式伪代码:

classMyList{

privateObject[] obj;

privateint size=0;

publicMyList(){

this(10);

}

publicMyList(int len){

obj=newObject[len];

}

publicvoid add(Object o){

obj[size]=o;

//为了实现可以一直向MyList中不断的添加元素.

change();

size++;

}

privatevoid change(){

Object[]old=obj;

obj=newObject[old.length*3/2]; //在原来数组基础上扩大50%

/*

for(inti=0;i<old.length;i++){

obj[i]=old[i];

}*/

}

publicString toString(){

StringBuilderbuilder=new StringBuilder();

builder.append("[");

for(inti=0;i<size;i++){

builder.append(obj[i]).append(",");

}

builder.deleteCharAt(builder.length()-1);

builder.append("]");

returnbuilder.toString();

}

}

LinkedList

LinkedList的底层实现:双向链表

LinkedList特殊的方法:它可以很方便的操作集合的头尾元素.

它对外提供了 get/remove/add

关于ArrayList与LinkedList集合区别?

ArrayList底层是使用数组实现,在内存中是连续的空间,那么他在做查找时会方法,

但是在做删除/修改时效率比较低.

LinkedList它的底层实现是链表实现,它在做查找时效率比较低。转为每一个元素

头存储的是上一个元素的地址,尾存储的是下一个元素的地址。

但是,它在做删除与修改时效率高。

LinkedList集合的特性方法

1.addFirst/addLast

声明:public void addFirst(Object obj);

作用:将obj元素添加到集合的首位置

声明:public void addLast(Object obj)

作用:将obj元素添加到集合的尾位置

//在jdk1.6后提供两个替代的方法

offerFirst

offerLast

它与我们addFirst与addLast区别在于它有返回值.

2.getFirst/getLast

声明:public Object getFirst();

作用:得到集合中的首元素

声明:public Object getLast();

作用:得到集合的尾元素

在jdk1.6后提供替代方法

peekFirst

peekLast

它们与getFirst/getLast区别,它们在集合为空时,返回的是null,而不会产生异常.

3.removeFirst/removeLast

声明:public Object removeFirst();

作用:删除集合中的首元素,返回的就是删除的这个元素

声明:public Object removeLast()

作用:删除集合中的最后一个元素,返回的是删除的这个元素.

jdk1.6后替换的方法

pollFirst

pollLast

它们区别在于pllFirst/pollLast列表为空时不会产生异常,而是返回null;

注意:对于getFirst/getLastremoveFirst/removeLast时,如果集合为空

会产生异常.

Vector

Vector是早期应用集合时所使用的一个类.

ArrayList是Vector的替代类.

ArrayList是数组实现,它是每次增加50%,线程不安全.

Vector是数组实现 它每次拉回100%,线程安全的。

关于使用Enumeration遍历Vector

//1.得到Enumeration对象

Enumeration enu=v.elements();

//2.判断是否有元素可以进行迭代

while(enu.hasMoreElements()){

//3.得到元素

Object obj=enu.nextElement();

System.out.println(obj);

}

List集合的总结

List有顺序可重复.

|----ArrayList

它的底层实现是使用数组,每次增长50%,在做查询操作时效率高。是线程不安全。

|----LinkedList

它的底层实现是使用链表,它在做修改与删除时效率高。线程不安全。

Linkedlist对于首尾元素操作比较方便.

|----Vector

它的底层实现是数组,每次增长100%,效率低下,线程安全。

对于List集合的遍历方式

1.Iterator

2.get+索引

3.listIterator

Set

Set集合:无顺序不可重复

|----HashSet

它是由hash表支持的。这使用hashCdoe与equals来维护元素的唯一

|----TreeSet

对于Set集合,如果想要遍历出所有元素,只能使用迭代器.

元素不重复,是指元素做equals为true,代表重复.

HashSet怎样保证元素唯一

1.两个元素的hashCode不一样,不会判断equals,直接就能装入.

2.两个元素的hashCode一样,equals为false,能装入

3.两个元素的hashCdoe一样,equals为true,不能装入.

做equals相等的对象的hashCode值应该一样.

我们重写hashCode方法时怎样重写

就是将所有的做equals比较进应用的属性的hashCode值进行相加就可以,

为了减少重复的概率,我们可以定义一个质数,用这个质数与

所有的属性相乘,这样使用的hashCode值重复概率减少.

TreeSet集合的特点:有顺序不可重复

TreeSet集合怎样保证集合中的的元素是有顺序的,怎样保证元素的唯一性

TreeSet集合中的元素必须有自然顺序或给集合指定了比较器。

1.使用自然顺序

就是实现 Comparable接口,重写compareTo方法

怎样排序:根据compareTo方法的返回值是正数还是负数,知道大于还是小于.

怎样唯一:根据compareTo方法的返回值为0,知道重复.

2.使用比较器

就是实现 Comparator接口 重写compare方法。

怎样排序:根据compare方法的返回值是正数还是负数,知道大于还是小于.

怎样唯一:根据compare方法的返回值为0,知道重复.

注意:使用比较器要在创建集合时,就将其做为参数传递给集合。

什么时候使用比较器?

我们在开发中,发现集合中的元素已经存在了自然顺序,但是我们

想要进行排序的条件不是按照元素的自然顺序排序。这时就可以

自己去做比较器。

Set

|----HashSet 底层使用的hash表无顺序不重复,线程不安全的。 这是使用hashCode和equals方法保证元素唯一

|------LinkedHashSet

元素装入顺序与取出顺序一致.线程不安全

|----TreeSet

底层使用二叉树有顺序,不可重复 线程不安全的.TreeSet在使用时效率比较低。

它保证元素唯一有两种方式

1.自然顺序 Comparable----compareTo(Object obj)

2.比较器 Comparator----compare(Object o1,Object o1)

怎样选择List与Set集合

通常使用List,首先ArrayList ,如果是操作头尾元素还有频繁进行删除修改操作这时选择LinkedList

如果要求元素是不重复的。

这时就选择Set ,首先HashSet

如果要求对元素进行排序 TreeSet.

jdk1.5,jdk1.6中TreeSet集合在使用时,如果是装入的第一个元素,

这个时候它不会进行比较。也就是compareTo方法不会被执行.

jdk1.7后集合中元素必须有自然顺序,也就是说当装入元素时,

无论是否是第一个都会执行compareTo方法。

泛型

泛型:其实就是用来限定类型.

泛型的优点:

1.提高了我们程序的使用性.不需要在自己去做强转.

2.将原来在运行阶段处理的问题,放到了编译阶段.

3.提高安全性.

在我们学习过程中,使用泛型最多的就是在集合中。

泛型可以声明在类上,可以声明在方法上,可以声明在接口上。

声明在类上的泛型,在整个类的范围内都可以使用。

声明在方法上的泛型,只能在方法上使用。什么时候在方法上声明泛型?

类上已经声明了泛型,但是在方法上我们不使用类上的泛型,而是自定义的

一个,那么就可以在方法上声明,注意:在方法上声明时,泛型要定义在方法的返回值前面。

通配符: ? 泛型中使用通配符的限定

<?extends E> 它是用来限定是E类型或是E的子类型.

<?super E> 只能是E类型或E的父类型.

1.关于迭代器中使用泛型

集合上定义了泛型,我们在使用迭代器进行迭代操作时,必须给迭代器

也指定泛型,这样,在迭代出来时就不需要进行强制转换。

2.关于泛型的擦除.

泛型只对编译阶段有效,而在运行阶段就失效。

/*

//以下两种操作,不建议使用,什么情况下能使用,就是为了兼容以前定义的集合.

Listlist1=new ArrayList<String>();

list1.add("abc");

list1.add(123);

List<String>list2=new ArrayList();

list2.add("abc");

list2.add(123);

*/

ArrayList<String>list=new ArrayList<>(); //在jdk1.7后可以,简化操作,<>代表<String>

Map集合

Map集合是一种双列集合,它是采用key-value映射方式存储的。

它的key值不能重复。

Map接口下提供方法

1.怎样将元素添加到Map集合中.(*****)

声明: public Object put(Object key,Object value)

作用:向Map集合中添加key与value,

注意:如果key值重复,它会将原本的映射关系破坏,

用新的元素将旧的元素替换,而返回值就是旧的元素.

2.clear

声明:public void clear();

作用:清空集合

3.size

声明:public int size();

作用:得到集合的长度()

4.containsKey containsValue

声明: public boolean containsKey(Object key)

public boolean containsValue(Objectvalue)

作用:判断Map集合中是否包含指定的key或value

5.根据key取得value get

声明:public Object get(Object key)

作用:根据指定的key值,得到对应的value。

注意:如果没有映射关系,返回的是null.

6.remove

声明 public Object remove(Object key)

作用:根据key删除映射关系.

返回值返回的是这个key对应的value值

7.values

声明:publicCollection values();

作用:得到Map集合中的所有的value的值的一个Collection集合。

Map集合的遍历操作

1.使用keySet

1.通过Map的keySet方法得到的是key的Set视图.

2.通过Iterator对Set集合进行迭代,将Map中的所有的key得到了

3.通过Map的get方法,根据key得到对应的value.

2.使用entrySet

1.通过Map的entrySet方法得到的是key-value(其实就是Entry类型)映射的Set视图

2.通过Iterator得到Set集合中的所有的Entry对象.

3.通过Entry对象的getKey getValue方法得到Map集合中的所有的key与value.

Map集合与Collection集合的区别

1.Map是双列集合 Collection是单列集合

2.Map集合存储是使用put方法

Collection存储使用的是add方法.

3.Map集合不能直接使用迭代器遍历.

使用keySet或entrySet方法,得到一个Set集合,在使用迭代器将Map集合中的元素迭代出来。 Collection取值使用迭代器 Iterator

HashMap

HashMap

HashMap允许null值与null键,线程不安全。

它的底层实现是基于hash表的。

HashMap怎样保证其key值不重复?

使用元素的hashCode方法与equals方法保证.

Hashtable

Hashtable不允许null值null键,它是线程安全。

TreeMap

它的底层实现使用的二叉树。它也是线程不安全的。

它怎样保证key的唯一性?

1.自然顺序

2.比较器

与我们之前讲过的TreeSet一样的原理.

Map集合总结

Map 双列集合

|-----HashMap 底层使用hash表实现,它允许null值,null键,线程不安全。

HashMap使用元素的hashCode与equals方法来保证key的唯一。

|------LinkedHashMap

它保证了装入时的key的顺序与取出时key的顺序一样。

|-----Hashtable 它与HashMap的区别,除了不能null值,null键,线程安全。其它一样。

|------Properties

它是对配置文件进行映射的。

在早期开发中,经常的使用这样原的文件进行配置。

|-----TreeMap 底层实现二叉树,它线程不安全。

它使用 自然顺序与比较器保证 key的唯一.

怎样选择使用什么集合

1.判断是存储单列还是双列,这样就可以选择Collection还是Map

2.

2.1Collection

如果没有要求,先List,List下首选ArrayList

如果要求不重复 Set,Set下首先HashSet.

对于LinkedList,TreeSet,它们的使用要根据上体的特性。

2.2Map

首选HashMap,如果要求进行排序,TreeMap.

今日小练习:

将前面日志中的扑克牌程序用集合重写,并提供洗牌的功能.

Package com.itheima.test

import java.util.*;
class
Test2{
public
static void
main(String[] args){
List<Poker> ps=new
ArrayList<Poker>();
PokerTools.createPoker(ps);
PokerTools.shuffle(ps);
PokerTools.show(ps);
}
}
//关于扑克的一些操作
class
PokerTools{
//生成扑克方法
public
static void
createPoker(List<Poker> ps){
for(int i=0;i<GlobalPoker.cs.length;i++){
for(int j=0;j<GlobalPoker.ns.length;j++){
ps.add(new
Poker(GlobalPoker.cs[i],GlobalPoker.ns[j]));
}
}
}

//洗牌的方法
public
static void
shuffle(List<Poker> ps){
Random ran=new
Random();
for(inti=0;i<ps.size();i++){
intn=ran.nextInt(ps.size());
Poker p1=ps.get(i);
Poker p2=ps.get(n);
ps.set(i,p2);
ps.set(n,p1);
}
}
//显示扑克牌的方法
public
static void
show(List<Poker> ps){
for(inti=0;i<ps.size();i++){
if(i%GlobalPoker.ns.length==0){
System.out.println();
}
System.out.print(ps.get(i)+" ");
}
}
}
//这个类中定义的是一个常量
class
GlobalPoker{
public
static final

String[] cs={String.valueOf((char)3),String.valueOf((char)4),String.valueOf((char)5),String.valueOf((char)6)};
public
static final

String[] ns={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
}
class
Poker{
String
color;
String
number;
public Poker(){}
public Poker(String color,String number){
this.color=color;
this.number=number;
}
// 重写toString方法
public
String toString(){
return
color+number;
}
}

------- android培训java培训、期待与您交流!
----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: