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

黑马程序员 集合框架

2015-06-30 01:15 537 查看
                                                                                          集合框架

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

1.为什么出现集合类?

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。 

2.数组和集合类同是容器,有何不同?

数组虽然也可以存储对象,但长度是固定的,集合长度是可变的,数组中可以存储基本数据类型,集合只存储对象。

3.集合类的特点

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。集合中存储的都是对象的引用(地址)

4.出现多个容器的原因:因为每一个容器对数据的存储方式都不同,这个存储方式称为数据结构。

5.集合框架的共性方法

ArrayList a1=new ArrayList();

//添加元素,a1.add(Object obj);add方法的参数类型是Object,以便于接收任意类型对象

a1.add(“java01”);

a1.add(“java02”);

a1.add(“java03”);

//删除元素

a1.remove(“java02”);

a1.clear();//清空集合

//判断元素

a1.contains(“java03”);

a1.isEmpty();//判断集合是否为空

//获取集合长度

a1.size();

ArrayList a2=new ArrayList();

a2.add(“java01”);

a1.retainAll(a2);//取交集,a1中只会保留和a2中相同的元素。

a1.removeAll(a2)//去交集,a1中只会保留和a2中不相同的元素。

6.什么是迭代器?

其实就是集合的取出元素的方式。

(1)当取出这个动作不足以用一个函数来描述,需要用多种功能来体现,那么就把取出这个动作封装成一个对象,通过内部类来描述对象,这样可以直接访问集合内部的元素。

(2)每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取。

(3)这些内部类都符合一个规则,该规则是Iterator。如何获取集合的取出对象呢?通过一个对外提供的方法。Iterator();

(4)Collection中有iterator(),所以每一个子类集合对象都具备迭代器。

(5)迭代器的常见操作

   hasNext();//有下一个元素,返回真

   next();//取出下一个元素

   remove();//移除

有两种迭代方式:

第一种:

ArrayList a1=new ArrayList();//创建一个集合

Iterator it=a1.iterator();//获取一个迭代器,用于取出集合中的元素。

while(it.hasNext())

{

sop(it.next());

}

第二种:

ArrayList a1=new ArrayList();//创建一个集合

for(Iterator it=a1.iterator();it.hasNext();)

{

sop(it.next)

}

(6)迭代注意事项

a.迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。

b.迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。

c.迭代器的next方法返回值类型是Object,所以要记得类型转换。

7.List集合

(1)Collection中常见的两种集合:

List:元素是有序的,元素可以重复,因为该集合体系有索引。

  ArrayList:底层的数据结构使用的是数组结构;特点:查询速度              快,增删速度慢,线程不同步。ArrayList的长度是              可变化的(默认长度是10),当元素超过默认长度,               ArrayList会自动延长50%的长度

  LinkeList:底层使用的是链表数据结构;特点:增删速度快,

             查询速度慢

  Vector:底层是数组数据结构,线程同步。增删,查询都很慢,被          ArrayList替代。Vector的长度是可变化的(默认长度是          10),当元素超过默认长度,Vector会延长100%

Set:元素是无序的,元素不可以重复。

(2)List特有方法:凡是可以操作角标的方法都是该体系特有的方法。

增:

add(index,element);//在指定位置添加元素

addAll(index,Collection);//在指定位置添加集合元素

删:

remove(index);//删除指定位置的元素

改:

set(index,element);//修改指定位置的元素

查:

get(index);//获取角标元素

subList(from,to);//获取部分元素

listIterator();//通过迭代方法获取全部元素

indexOf(obj);//获取对象位置,如果没有该对象则返回-1。

(3)ListIterator是Iterator的子接口,是List集合特有的迭代器。因为Iterator方法是有限的,同时在迭代时,不可以通过集合对象的方法操作集合中的元素。否则会发生ConcurrentModificationException异常。所以可以通过ListIterator方法拓展对元素的操作。(注意:该接口只能通过List集合的listIterator方法获取)

(4)ListIterator特有的方法

     add(obj);//增加

     set(obj);//修改     

     hasPrevious();//判断前面有没有元素

     previous();//取前一个元素

(5)Vecter

枚举: 就是Vector特有的取出方式。Vector有三种取出方式。

其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。

特有方法:

Vecter v=new Vector();

v.add(“java01”);

Enumeration en=v.elements();

While(en.hasMoreElements())

{

sop(en.nextElements());

}

hasMoreElements();//相当于Iterator的hasNext()方法

nextElements();//相当于Iterator的next()方法

8.LinkedList

特有方法:

addFirst();//将元素添加在最前面

addLast();//将元素添加在最后面

getFirst();//获取第一个元素

getLast();//获取最后一个元素

removeFirst();//获取第一个元素并从集合中删除该元素

removeLast();//获取最后一个元素并从集合中删除该元素

(注意:get方法和remove方法中,如果集合没有元素,则会出现NoSuchElementException)

使用方法:

//创建一个LinkedList 类型的集合对象link

LinkedList link=new LinkedList();

link.addFirst(“java01”);

link.addLast(“java02”);

sop(link.getFirst());

sop(link.getLast());

sop(link.removeFirst());

sop(link.size());

sop(link.getLast());

在JDK1.6出现替代方法

offerFirst();//添加元素

offerLast();

peekFirst();//获取元素,但不删除元素

peekLast();

pollFirst();//获取元素,而且删除元素

pollLast();

(注意:peek方法和poll方法中,如果集合没有元素,则会返回null)

练习一:

<span style="font-size:14px;">//使用LinkedList模拟一个堆栈或者队列数据结构队
import java.util.*;
class DuiLie
{
private LinkedList link;
DuiLie()
{
link=new LinkedList();
}
public void myAdd(Object obj)
{
link.addFirst(obj);//先进,在首位添加元素
}
public Object myRemove()
{
return link.removeLast();//先出,删除末尾的元素
}
public boolean isNull()
{
return link.isEmpty();//判断集合是否为空
}
}
class LinkedListTest
{
public static void main(String[] args)
{
DuiLie d=new DuiLie();
d.myAdd("java01");
d.myAdd("java02");
d.myAdd("java03");
d.myAdd("java04");
while(!d.isNull())
{
System.out.println(d.myRemove());
}
}
}</span>


练习二:

//去除ArrayList集合的重复元素。
import java.util.*;
class ArrayListTest
{
public static ArrayList singleElement(ArrayList a1)
{
ArrayList a2=new ArrayList();//创建集合a2
Iterator it=a1.iterator();//获取a1迭待器
while(it.hasNext())
{
/*判断a2集合里是否已存在该元素,
不存在则将元素存在a2集合里*/
Object obj=it.next();
if(!a2.contains(obj))
a2.add(obj);
}
return a2;
}
public static void main(String[] args)
{
ArrayList a1=new ArrayList();//创建集合a1
//添加元素
a1.add("java01");
a1.add("java02");
a1.add("java01");
a1.add("java02");
a1.add("java03");
System.out.println(a1);
a1=singleElement(a1);//调用函数
System.out.println(a1);

}
}


练习三:

/*
将自定义对象作为元素存到ArrayList集合中,
并去除重复元素 。
*/
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
/*
Object里面的equals方法是比较对象的地址值,然而每个对象的
地址值都不一样,不能够作为本程序的判断方法。所以要按照自身
的需求覆写Object里面的equals方法作为contains方法里的判断条件。
注意:euqals方法是自动被调用的。
*/
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p=(Person)
ffb4
obj;
return this.name.equals(p.name) && this.age==p.age;
}
public String getName()
{
return name;
}

public int getAge()
{
return age;
}
}
class ArrayListTest2
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList a1=new ArrayList();
a1.add(new Person("name1",1));
a1.add(new Person("name1",1));
a1.add(new Person("name2",2));
a1.add(new Person("name2",2));
a1.add(new Person("name3",3));
a1.add(new Person("name3",3));
a1=singleElement(a1);
Iterator it=a1.iterator();
while(it.hasNext())
{
/*因为迭代器里面返回的都是Object,要使用Person里面的方法,
就要对象向下转型Object obj=it.next()
Person p=(Person)obj;即:Person p=(Person)it.next()
*/
Person p=(Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}

public static ArrayList singleElement(ArrayList a1)
{
ArrayList a2=new ArrayList();
Iterator it=a1.iterator();
while(it.hasNext())
{
Object obj=it.next();
if(!a2.contains(obj))
a2.add(obj);
}
return a2;
}
}


9.
(1)Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。
(a)HashSet:底层数据结构是哈希表。
(b)HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的HashCode值不同,不会调用equals。注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
(c)TreeSet:可以对Set集合的元素进行排序,底层数据结构是二叉树(小的存左,大的存右),保证元素唯一性的依据:compareTo方法return 0。(注意:排序时,当主要条件相同时,一定判断一下次要条件)
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。
(2)集合的功能和Collection是一致的。

10.泛型
(1)概述:JDK1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制。
(2)好处
(a)将运行时期出现问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时问题减少,安全。
(b)避免了强制转换的麻烦。
(3)泛型格式:通过<>来定义要操作的引用数据类型。
(4)在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型。
(5)什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候。
格式:
class Xxx<QQ>
{}
class Yyy
{  public static void main(String[] args)

{

Xxx<QQ> x=new Xxx<QQ>();

}
}

(6)泛型类定义的泛型在整个类中有效,如果被方法使用,那么泛型的对象明确要操作具体类型后,所有要操作的类型已经固定。
(7)为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
格式:public <T> void show(T t){}
(8)静态方法泛型的特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
格式:public static <T> void show(T t){}

(9)泛型接口:
格式:
Interface Inter<T>
{void show(T t);}
Class InterImpl implements Inter<String>

     public void show(String t){}
}

(10)泛型限定
?通配符,也可以理解为占位符。
? extends E:可以接收E类型或者E的子类型,上限。
? super E:可以接收E类型或者E的父类型,下限。
局限性:不可以使用引用数据类型的特有方法。
import java.util.*;
class GenericDemo
{
public static void main(String[] args)
{
//添加了比较器,按照比较器的要求排序
//a1集合的元素为Student类型
TreeSet<Student> a1=new TreeSet<Student>(new Comp());
a1.add(new Student("stu01"));
a1.add(new Student("stu03"));
a1.add(new Student("stu02"));
Iterator<Student> it=a1.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}

//a2集合的元素为Worker类型
TreeSet<Worker> a2=new TreeSet<Worker>(new Comp());
a2.add(new Worker("work01"));
a2.add(new Worker("work03"));
a2.add(new Worker("work02"));

Iterator<Worker> it2=a2.iterator();
while(it2.hasNext())
{
System.out.println(it2.next().getName());
}
}
}

class Person
{
private String name;
Person(String name)
{
this.name=name;
}
public String getName()
{
return name;
}

}
class Student extends Person//继承关系
{	Student(String name)
{
super(name);//调用父类的构造方法
}
}
class Worker extends Person//继承关系
{
Worker(String name)
{
super(name);
}
}
class Comp implements Comparator<Person>//比较器
{
public int compare(Person p1,Person p2)
{
return p1.getName().compareTo(p2.getName());
}
}

11.Map集合
(1)概述:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
(2)方法
添加:
put(K key, V value)
/*如果出现添加时,相同的值,那么后添加的值会覆盖原有键对应的值,并put方法会返回被覆盖值。*/
删除:
clear()
判断:
containsKey(Object key)
containsValue(Object value)
isEmpty()
获取:
get(Object key)
/*可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断*/
size()
values()
(3)Map的三部分
Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的,效率低,jdk1.0。
HashMap:底层是哈希表数据结构,允许使用null键,该集合是不同步的,效率高,jdk1.2。
TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
(小知识:Set底层就是使用了Map集合)
(4)Map集合的两种取出方式
keySet:将Map中所有的键存入到Set集合,因为Set具备迭代器。
所以可以通过迭代方式取出所有的键,在根据get方法,获取每一个键对应的值。
Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了Set集合中,而这个关系的数据类型是:Map.Entry。(其实Entry也是一个接口,它是Map接口中的一个内部接口)
练习一:
/*
keySet:将Map中所有的键存入到Set集合,因为Set具备迭代器。
所以可以通过迭代方式取出所有的键,在根据get方法,获取每一个键对应的值。
*/
import java.util.*;
class KeySetDemo
{
public static void main(String[] args)
{
//创建Map集合并定义泛型
Map<String,String> map=new HashMap<String,String>();
map.put("04","lisi04");
map.put("02","lisi02");
map.put("01","lisi01");
map.put("03","lisi03");
//将Map集合中的键存放在Set集合中
Set<String> keySet=map.keySet();
//获取Set集合的迭待器
Iterator<String> it=keySet.iterator();
while(it.hasNext())
{
String key=it.next();
String value=map.get(key);//通过键获取该键对应的值
System.out.println("key:"+key+";value:"+value);
}
}
}
练习二
/*
Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了Set集合中,
而这个关系的数据类型是:Map.Entry。
*/
import java.util.*;
class EntrySetDemo
{
public static void main(String[] args)
{
//创建Map集合
Map<String,String> map=new HashMap<String,String>();
map.put("04","lisi04");
map.put("02","lisi02");
map.put("01","lisi01");
map.put("03","lisi03");
//将映射关系存放在Set集合里面
Set<Map.Entry<String,String>> entrySet=map.entrySet();
//获取Set集合的迭待器
Iterator<Map.Entry<String,String>> it=entrySet.iterator();
while(it.hasNext())
{	//提取映射关系,直接获取键值和键值对应的值
Map.Entry<String,String> me=it.next();
String key=me.getKey();
String value=me.getValue();
System.out.println("key:"+key+";value:"+value);
}
}
}

练习三

/*
1.描述一个学生
2.定义map容器,将学生作为键,地址作为值,存入。
3.获取map集合中的元素。
*/
import java.util.*;
class MapTest
{
public static void main(String[] args)
{
HashMap<Student,String> hm=new HashMap<Student,String>();
//注意Map集合添加元素方法是put,而不是add
hm.put(new Student("lisi01",21),"beijing");
hm.put(new Student("lisi03",23),"guangdong");
hm.put(new Student("lisi02",22),"shanghai");
//第一种取出方式:取出键!
Set<Student> keySet=hm.keySet();
Iterator<Student> it=keySet.iterator();
while(it.hasNext())
{
Student stu=it.next();
String addr=hm.get(stu);
System.out.println("Student:"+stu+"...addr:"+addr);
}

//第二种取出方式:取出映射关系!
Set<Map.Entry<Student,String>> entrySet=hm.entrySet();
Iterator<Map.Entry<Student,String>> it2=entrySet.iterator();
while(it2.hasNext())
{
Map.Entry<Student,String> me=it2.next();
Student stu=me.getKey();
String addr=me.getValue();
System.out.println("Student:"+stu+"_ _ _addr:"+addr);

}
}
}

class Student
{	private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+":"+age;
}
//自定义对象需要覆写hashCode方法和equals方法
public int hashCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s=(Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
}


12.方法的可变参数

当函数的参数列表是同一类型,那么可以将参数隐式地封装在数组里

13.StaticImport 静态导入

(1)当类名重名时,需要指定具体的包名;

当方法重名时,指定具备所属的对象或者类。

(2)import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。

(3)import static java.lang.System.*;//导入了System类中所有静态成员

14.Date

Date d=new Date();

System.out.println(d);//打印的时间看不懂

SimpleDateFormat adf=new SimpleDateFormat(“yyyy年MM月dd日 E hh:mm:ss”);//将模式封装到SimpleDateFormat对象中。

String time=adf.format(d);//调用format方法让模式格式化指定Date对象



15.Calendar

Calendar c=Calendar.getInstance();//获取对象

c.set(2012,2,1);//设置时间:2012年3月1日 (0~11表示1~12月)

c.add(Calendar.DAY_OF_MONTH,-1)//3月1日往前推一天就是2月的最后一天。

c.add(Calendar.MONTH)//获取年

c.add(Calendar.DAY_OF_WEER)//获取星期

c.add(Calendar.YEAR)//获取年

16.Math

(1)double d=Math.ceil(16.34);//返回大于指定数据的最小整数。

(2)double d1=Math.floor(12.34)//floor返回小于指定数据的最大整数。

(3)long l=Math.round(12.54);//四舍五入

(4)double d2=Math.pow(2,3);//2的3次方

(5)Random r=new Random();

for(int x=0;x<10;x++)

{

//随机取出10个包含10不包含包0的整数

//int d=(int)(Math.random()*10+1);

int d=r.nextInt(10)+1;

sop(d);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: