黑马程序员 集合框架

来源:互联网 发布:深圳java外包公司 编辑:程序博客网 时间:2024/05/10 03:02

                                                                                          集合框架

------- <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();//创建集合a2Iterator 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)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,而不是addhm.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(“yyyyMMdd日 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);

}


0 0
原创粉丝点击