黑马程序员-学习日记
黑马程序员_JAVA中集合框架1(Collection,List,Set及其子类和迭代器的应用)
------- android培训、java培训、期待与您交流! ----------
一:集合是用于存储对象的一个工具。
集合和数组的特点:
1.相同点:
集合和数组都一个容器。
2.集合:
1,可以存储对象,只能存储对象。
2,集合的长度的是可变的。
3.数组:
1,可以存储对象,也可以存储基本数据类型值。
2,数组长度的是固定的。
注意:CollectionDemo.java 使用了未经检查或不安全的操作。注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。
Java编译器认为该成存在安全隐患。友情提示:但并不是编译失败,所以可以不用理会。
其实是因为类型的原因导致的,用了泛型以后,就没有该提示了。
二:集合中的一般方法:
importjava.util.*;
classCollectionDemo{
public static void main(String[] args){
Collection coll = new ArrayList();//创建了一个集合对象.也就是一个容器。
//添加元素。add();
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
System.out.println("集合的元素:"+coll);
//删除元素。
boolean b =coll.remove("abc2");
System.out.println("b="+b);
//获取集合的长度。
int size = coll.size();
System.out.println("size="+size);
//清除集合中的所有元素。
coll.clear();
//判断:
boolean b = coll.isEmpty();//其实内部依据的是size()方法。如果size()=0,就返回true。
System.out.println("b="+b);
boolean b=coll.contains("abc1");
System.out.println("b="+b);
//简单的获取集合所有元素。直接将集合的元素打印到控制台。
System.out.println("操作后的集合:"+coll);
}
}
三:Collection中带All的方法用法集合:
import java.util.*;
class CollectionDemo2 {
public static void main(String[] args) {
Collection coll = new ArrayList();//创建了一个集合对象.也就是一个容器。
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
System.out.println("集合的元素:"+coll);
Collection co2 = new ArrayList();
co2.add("abc3");
co2.add("abc2");
co2.add("abc1");
co2.add("abc4");
Collection co3 = new ArrayList();
co3.add("abc7");
co3.add("abc8");
//添加一堆元素。
//coll.addAll(co2);//将co2中的元素添加到coll集合中。[abc1, abc2, abc3, abc5, abc]
//判断一堆元素是否存在。
boolean b = coll.containsAll(co3);
System.out.println("b="+b);
//删除一堆元素。
boolean b1 =coll.removeAll(co3);//removeAll会将coll中包含的和co3相同的元素删除。
System.out.println("b1="+b1);
//获取两个集合的交集。
boolean b=coll.retainAll(co2);//retainAll会将coll和co2中相同的元素保留在coll中。
//所以coll中存储就是交集的元素。当coll集合中的元素变化时,retainAll方法返回true。
//当coll集合中的元素本身就是交集元素,不发生变化。那么返回false。
System.out.println("b="+b);
System.out.println(coll);
}
}
四:Collection集合中对元素的获取方法:
import java.util.*;
class IteratorDemo{
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
//只要是Collection集合体系,迭代器就是通用取出方式。
/*
Iterator it = coll.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
*/
for(Iterator it = coll.iterator() ;it.hasNext(); ){
System.out.println(it.next());
}
}
}
五:LinkedList的特有方法:
1:addFirst();
addLast();
在jdk1.6以后被
offerFirst();
offerLast();替代
2:获取元素,集合的长度不改变:
如果集合中没有元素,那么该方法会发生异常NoSuchElementException
getFirst():
getLast();
在jdk1.6以后被
peekFirst();
peekLast();替代
如果集合元素没有,该方法不会抛出异常,而是返回null。
3:获取元素,但是该元素会被删除出集合,集合的长度会改变:
如果集合中没有元素,那么该方法会发生异常NoSuchElementException
removeFirst():
removeLast();
在jdk1.6以后被:
pollFirst();
pollLast();替代
如果集合元素没有,该方法不会抛出异常,而是返回null。
import java.util.*;
class LinkedListDemo {
public static void main(String[] args) {
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
System.out.println(link.getFirst());
System.out.println(link.removeFirst());
System.out.println(link);
while(!link.isEmpty()){
System.out.println(link.removeFirst());
}
}
}
六:List集合中常见的共性方法:List:该容器的元素是有序的(存储的顺序和取出的顺序一致) 该集合中的元素都有索引(角标).该集合可以存储重复的元素。
1,添加元素:add();
2,删除元素:remove();
3,修改元素: set();
4,获取元素:get();
import java.util.*;
class ListDemo{
public static void main(String[] args){
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
System.out.println("原集合:"+list);
//添加功能。在指定位置插入元素。
list.add(1,"haha");//在1索引为插入元素 haha.其他元素依次顺延。
//按照指定索引删除元素。会返回被删除的元素。
System.out.println("remove(1):"+list.remove(1));
//最指定位置的元素进行修改。会返回被修改掉的元素.
System.out.println("set(0,kk)="+list.set(0,"kk"));
//通过索引获取指定元素。
System.out.println("get(1):"+list.get(1));
//通过元素获取到第一次出现位置。
System.out.println("indexOf(abc2)="+list.indexOf("abc2"));
//根据头尾角标获取子列表。
List newList = list.subList(0,2);//全取list.subList(0,list.size());
System.out.println("自列表是:"+newList);
//通过List特有的方式,获取集合中所有的元素。
for(int x=0; x<list.size(); x++){
System.out.println(list.get(x));
}
System.out.println("操作后:"+list);
}
}
七:List:有序,可重复,有索引:
|--ArrayList:底层数据结构是数组结构。线程不安全的。所以ArrayList的出现替代了Vector.但是查询的速度很快.
|--Vector:底层数据结构是数组结构。jdk1.0版本。线程安全的。无论增删还是查询都非常慢。
|--LinkedList:底层是链表数据结构。线程不安全的,同时对元算的增删操作效率很高
可变长度的数组:
ArrayList内部封装了一个默认长度为10的数组;当超出长度时,集合内部会自动生成一个新的数组;将原数组中的元素复制到新数组中,在将新元素添加到新数组。
新数组的长度:
ArrayList 50%延长。
Vector 100%延长。
Vector中提供了一个独特的取出方式,就是枚举Enumeration;此接口Enumeration的功能与 Iterator 接口的功能是重复的
Enumeration的名称和方法的名称过程,书写很麻烦;所以被Iterator所取代,郁郁而终。
import java.util.*;
class VectorDemo{
public static void main(String[] args) {
Vector v = new Vector();
v.addElement("abc1");
v.addElement("abc2");
v.addElement("abc3");
v.addElement("abc4");
Enumeration en = v.elements();
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
Iterator it = v.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
八:列表迭代器的应用:
在进行迭代过程中,如果出现了迭代器和容器同时对元素进行操作的情况很容易引发ConcurrentModificationException并发修改异常.
解决:要么使用集合的方法操作元素,要么使用迭代器的方法操作元素;不要同时使用。
但是 迭代器Iterator中只有三个操作,判断hasNext,获取next,删除remove。
想要其他的操作时,比如添加,这个迭代器就不可以使用了。这时对于List集合,有一个新的迭代方式, 就是ListIterator 列表迭代器。
ListIterator本身也是Iterator的子接口。并提供了更多的迭代过程中的操作在迭代过程中,如果需要增删改查元素的操作,需要列表迭代器。
但是注意:该迭代器,只能用于List集合。
import java.util.*;
class ListIteratorDemo{
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
ListIterator lit = list.listIterator();
System.out.println(lit.hasPrevious());
while(lit.hasNext()){
String s = (String)lit.next();
if(s.equals("abc2"))
//lit.add("haha");
lit.set("qq");
}
System.out.println(list);
System.out.println(lit.previous());
Iterator it = list.iterator();
while(it.hasNext()){
String s =(String)it.next();
if(s.equals("abc2"))
list.add("haha");//ConcurrentModificationException
System.out.println("s="+s);
}
System.out.println(list);
}
}
九:List和Set的用法区别:
A.|--List:有序(存的顺序和取的顺序一致。),元素可以重复,元素都有索引。
|--ArrayList:
|--LinkedList:
|--Set:无序,不可以重复元素。Set接口的方法和Collection中的方法一致。
Set接口取出元素的方法只有迭代器。
|--HashSet:底层数据结构是哈希表。哈希表这种结构,其实就是对哈希值的存储。
而且每一个对象都有自己的哈希值。因为Object类中的有一个方法hashCode方法。
B.如何保证元素唯一性的呢?
通过判断元素的hashCode方法,和equals方法完成的;
当hashCode值相同是,会在判断一次euqals方法的返回只是是否为true。
如果hashCode值不相同,就确定元素的哈希表中的位置,就不用在判断equals了。
当哈希表中有一个桶结构。每一个桶都有一个哈希值,当哈希值相同,但是equals为false时,表示为不同元素。
原理:这些元素都存放一个桶里。
|--TreeSet:可以对Set集合中的元素进行排序:
数据结构是二叉树数据结构。这种结构,可以提高排序性能。
1.它又是如何保证元素唯一性的呢?
是根据比较方法的返回值确定的:只要返回的是0,就代表元素重复。
2.HashSet集合保证元素唯一性的原因:
HashSet集合保证元素唯一性,依赖的是元素的hashCode方法和euqals方法。
当元素的哈希值不同时,元素都有自己的独立位置,不需要在判断元素的equals方法;
3.当元素的哈希值相同时,这时元素在哈希表中位置相同,这时就需要在判断一次元素的内容是否相同;就需要调用元素的equals方法进行一次比较。如果equals返回是true,那么视为两个元素为重复元素,只储存一个。如果返回是false,那么这两个元素不是重复元素,会存储在同一个哈希值上。
4.为了建立自定义对象判断元素是否重复的依据:
需要覆盖hashCode方法,和equals方法:而且最好依据对象的特有条件来建立hashcode和euqals的实现。
ArrayList:判断包含,以及删除,都是依据元素的equals方法。
HashSet:判断包含,以及删除,都是依据元素的hashCode方法。当hashCode值相同时,在判断一次equals方法。
实用小技巧:
ArrayList: 数组
LinkedList:链表
HashSet:哈希表
TreeSet:二叉树
看到Array就要想到数组,就要想到角标,就要想到查询很快.
看到Link就要想到链表.就要想要增删很快.最好再想到 addFirst(offerFirst)
看到Hash就要想要哈希表,就要想到元素的hashCode方法,和equals方法。
看到Tree,就要想要二叉树,就要想要排序。就要想到两个接口 Comparable 和Comparator。
需要明确的是什么时候List,什么时候用Set?
保证元素唯一,就用Set集合;不需要就使用List集合;实在搞不清楚,就用ArrayList。
Treeset集合使用于给元素进行排序的;那么自定义元素本身不具备比较性,Treeset集合是无法对元素进行排序的;
所以,在自定义对象时,需要对象具备一个扩展功能,用于比较的,
而java已经提供了接口,可以让实现它的对象具备比较性;那么自定义类,要想被Treeset排序,就需要实现Comparable接口;以具备比较功能。
比较的时候,要注意,主要条件和次要条件;如果主要条件相同,一定要比较次要条件。
当Treeset集合中存储的元素不具备比较功能;或者具备的比较功能不是所需要的。
例如:Person对象中的自然排序是按照年龄排序。
但是现在需求是想安装姓名排序。该源代码这种方式想都不要想。有这种想法就是犯罪。
该如何解决这个问题?
既然元素具备的比较方式不满足应用;这时,可以让集合自身具备比较性。
需要集合一初始化就具备比较功能。因为要在添加元素前具备。
就需要在构造函数进行初始化。
只要将一个实现了Comparator接口的子类对象作为参数传递给TreeSet集合的构造函数即可。
这样该集合就具备了比较功能。
建议使用第二种排序方式。
应用:
TreeSet排序方式有两种。
1,让元素自身具备比较性。
其实是让元素实现Comparable接口,覆盖compareTo方法。
这称为元素的自然排序。
2,当元素自身不具备比较性,或者元素具备的比较性不是所需要的,
可以让集合自身具备比较性。
定义一个比较器:
其实就是定义一个类,实现Comparator接口。覆盖compare方法。
将Comparator接口的子类对象作为参数传递给TreeSet的构造函数。
当元素自身具备比较性,同时TreeSet集合也具备比较器,这时以比较器为主。
十:学习了这么多,来一个总体总结:
一般在描述一个对象时,如果该对象封装了具体的数据,会出现很多这样的对象比如:员工,学生对象等.
这时就需要进行容器的存储.那么描述该类对象时,一定要复写几个方法:
1,hashCode()
2,equals()
3,toString()
4,最好实现Comparable接口让该类具备自然排序功能。
建立对象自身判断是否相同的依据,同时让对象具备基本的比较性。
代码体现:
class TreeSetDemo3{
public static void main(String[] args) {
TreeSet ts = new TreeSet(newCompareByName());
ts.add(new Person("lisi1",21));
ts.add(new Person("lisi4",29));
ts.add(new Person("lisi2",67));
ts.add(new Person("lisi8",28));
ts.add(new Person("lisi0",20));
System.out.println(ts);
}
}
//自定义一个比较器。
classCompareByName implements Comparator{
public int compare(Object o1,Object o2){
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int num =p1.getName().compareTo(p2.getName());
returnnum==0?p1.getAge()-p2.getAge():num;
}
}
class Personimplements Comparable{
private String name;
private int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
//人的自然排序是按照年龄排序
public int compareTo(Object obj){
Person p = (Person)obj;
int num = newInteger(this.age).compareTo(new Integer(p.age));
returnnum==0?this.name.compareTo(p.name):num;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public String toString(){
return name+"::"+age;
}
}
------- android培训、java培训、期待与您交流! ---------- 详细请查看:http://edu.csdn.net/heima/