黑马程序员_集合框架(一)

来源:互联网 发布:c语言输出人名心形图案 编辑:程序博客网 时间:2024/05/16 12:39

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、集合框架概述

为什么会出现集合类:

对象用于封装特有的数据,对象多了就需要储存,如果对象的个数不确定,就用集合进行储存。


集合的特点:

1、集合只可以用于储存数据

2、集合是可变长度的

3、集合可以储存不同类型的对象

4、集合中储存的是对象的引用(地址),不可以储存数据类型值


集合和数组的区别:

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

2、集合只能储存对象,数组可以储存基本数据类型

3、集合可以储存不同数据类型,数组必须储存同一类型


为什么会有多个容器

因为每个容器对数据的储存方式不同,这种储存方式叫做数据结构。


二、Collection接口

Collection是框架的常用接口有List和Set两个常用的子接口

Collection:

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

|--Set:无序(存入和取出顺序有可能不一致),不可以储存重复元素。必须保证元素的唯一性。


Collection接口中常用的方法

1、添加

add(Object):添加一个元素

addAll(Collection):添加一个集合中的所有元素

2、删除

clear():将集合中元素全部删除,清空集合。

remove(obj):删除集合中的指定对象,注意删除成功,集合的长度会改变。

removeAll(collection):删除部分元素。部分元素和传入Collection一致。

al1.removeAll(al2):删除a1中和a2中重复的元素。

3、判断

boolean contains(obj):集合中是否包含指定元素

boolean containsAll(Collection):集合中是否包含指定的多个元素

boolean isEmpty():集合中是否有元素

4、获取

in size():集合中有几个元素

Iterator iterator():取出元素中的所有元素,迭代器

5、取交集

boolean retainAll(Collection):对当前集合中保留和指定集合中相同的元素。如果两个集合元素相同,返回false;如果retainAll修改了当前集合返回true

7、将集合变为数组

toArray()


三、迭代器接口

什么是迭代器:

迭代器是一个接口。作用:用于取集合中的元素

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

元素。

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

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

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


迭代器的常见操作:

hasNext():如果仍有元素可以迭代,则返回true

next():返回迭代的下一元素

remove():从迭代器指向的Collection中移除迭代器返回的最后一个元素

注意:迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException

在迭代时循环中使用一次next,就要hasNext判断一次

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

public static void main(String[] args) {   //创建一个集合容器,使用Collection接口的子类,ArrayList Collection coll = new ArrayList();coll.add("abc0");coll.add("abc1");coll.add("abc2");coll.add("abc3");//方法一Iterator it = coll.iterator();//获取一个迭代器,用于取出集合中的元素。while (it.hasNext()) {System.out.println(it.next());}//方法二推荐使用for(Iterator it = coll.iterator();it.hasNext();) {System.out.println(it.next());}}

四、List接口

List;有序,有索引,可重复

|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快,增删速度慢。

|--Linkedlist:底层数据结构是链表,线程不同步,增删元素的速度非常快。查询速度慢。

|--Vector:底层的数据结构就是数组,线程是同步的,Vector无论查询和增删都非常慢


List特有方法:

凡是可以操作角标的方法都是该体系特有的方法。

增:

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

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

删:

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

改:

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

查:

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

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

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

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

lastIndexOf(Object o):反向索引指定元素的位置

List subList(start,end):获取子列表


List集合因为角标有了自己的获取元素的方式:遍历

for(int x = 0;x<list.size();x++) 

{

sop("get:"+list.get(x));

}


ListIterator是Iterator的子接口,是List集合特有的迭代器。

因为ListIterator的方法有限,同时不能通过集合对象的方法操作集合中的元素。否则会发生ConcurrentModificationException并发生异常。

所以可以通过ListIterator方法拓展对元素的操作。


ListIterator特有的方法

add(object);//增加

set(object);//修改为

hasPrevious();//逆向遍历,如果存在返回true

previous();返回列表中的前一个元素


枚举Enumeration:

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

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


特有方法:

addElement(obj);//添加元素,相当于add(obj);

Enumerationelements();//Vector特有取出方式(枚举)

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

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


五、LinkedList

LinkedList底层使用的是链表数据结构。特点增删速度快查询慢

特有方法:

增加:

addFirst();//添加在头部

addLast();

删除:

removeFirst();//获取并删除链表中的第一个元素

removeLast();

获取:

getFirst()://获取不删除链表中的第一个元素如果链表为空,抛出NoSuchElementException

getlast();


在JDK1.6之后出现了替代方法

增加

offerFirst();

offerlast();

删除

pollFirst();//获取并删除链表中的第一个元素,如果链表为空返回null

pollLast();

获取

peekFirst();//获取链表中的第一个元素。如果链表为空返回null

peekLast();


对于list集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。


练习:去除ArrayList中重复的元素

//去除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);}}

六、Set接口

概述:

Set接口的元素是无序的,存入和存出数据不一致。元素不可以重复。

Set接口中方法和Collection中方法是一致的Set接口取出方式只有一种迭代器。

|--HashSet:底层数据结构是哈希表,线程是不同步的,无序,高效。

HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。

当元素的hashCode值相同时,才继续判断equals是否为true

如果为true,那么视为相同元素不存。如果false,那么存储。

如果hashCode不同,那么不判断equals,从而提高对象比较的速度。

|--LinkedHashSet:有序,HashSet的子类

|--TreeSet:对Set集合中的元素进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。


对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。

对于HashSet集合,判断元素是否存在或者删除元素,底层依据的是hashCode方法和equals方法。


代码示例:往HashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人,视为相同元素。

import java.util.*;class Person{private String name;private int age;Person(String name,int age){this.name = name;this.age = age;}public String getName(){return name;}//复写hashCode()和equals()方法便于调用public int hashCode(){return name.hashCode()+age*39;//一般要乘以一个数保证哈希值的唯一性}public boolean equals(Object obj){if(!obj instanceof Person)throw new RuntimeException("不是学生对象");Person p = (Person)obj;return this.name.equals(p.name) && this.age==p.age;}public int getAge(){return age;}}class  {public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {HashSet hs = new HashSet();hs.add(new Person("java01",11);hs.add(new Person("java02",12);hs.add(new Person("java03",13);hs.add(new Person("java02",12);Iterator it = hs.iterator();while(it.hasNext()){Person p = (Person)it.next();sop(p.getName()+p.getAge());}}}

TreeSet:

用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性

如果元素不具备比较性,在运行时会发生ClassCastException异常

所以需要实现Comparable接口,强制让元素具备比较性,复写compareTo方法


TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复不存。


TreeSet集合排序方式有两种。Comparable和Comparator

1:让元素自身具备比较性,需要元素对象实现Comparable接口覆盖compareTo方法

2:让集合自身具备比较性,需要元素对象实现Comparator接口的比较器,并且覆盖compare方法并将该类对象作为实际参数传递给TreeSet集合的构造函数。

第二种方法比较灵活


第一种方式示例:

import java.util.*;class TreeSetDemo {public static void main(String[] args) {TreeSet ts = new TreeSet();ts.add(new Student("lisi02",22));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi08",19));Iterator it = ts.iterator();while(it.hasNext()){Student stu = (Student)it.next();//强制转换回来System.out.println(stu.getName()+"..."+stu.getAge());}}}class Student implements Comparable//该接口强制让学生具备比较性。{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;}//复写compareTo方法public int compareTo(Object obj){if(!(obj instanceof Student))throw new RuntimeException("不是学生对象");Student s = (Student)obj;//强制转换//先按年龄排,再按名字排System.out.println(this.name+"....compareto....."+s.name);if(this.age>s.age)return 1;if(this.age==s.age)//主条件相同时判断次要条件{return this.name.compareTo(s.name);}return -1;}}

第二种方式示例:

import java.util.*;class Student implements Comparable//该接口强制让学生具备比较性。{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;}}class TreeSetDemo2 {public static void main(String[] args) {TreeSet ts = new TreeSet();ts.add(new Student("lisi02",22));ts.add(new Student("lisi02",21));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi06",18));ts.add(new Student("lisi06",18));ts.add(new Student("lisi007",29));Iterator it = ts.iterator();while(it.hasNext()){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}}//定义一个类,实现Comparator接口,覆盖compare方法class MyCompare implements Comparator//先比较名字再比较年龄{public int compare(Object o1,Object o2){Student s1 = (Student)o1;//强制转换Student s2 = (Student)o2;int num = s1.getName().compareTo(s2.getName());if(num==0){return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));}return num;}}









0 0
原创粉丝点击