黑马程序员—集合框架

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

集合框架
Collection 接口
--List 元素是有序的,元素可以重复,因为该集合体系有索引
--ArrayList :底层的数据结构使用的是数组结构,查改较快,增删较慢
--LinkedList :底层使用的链表数据结构,查改较慢,增删较快
--Vector :底层是数组数据结构,功能同ArrayList相同


--Set 元素是无序的,元素不可以重复
--HashSet
--TreeSet
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都不同,这个存储方式称之为:数据结构


一、集合中常用方法
class CollectionDemo
{
public static void main(String[] args){
// 创建一个集合容器,使用Collection接口的子类:ArrayList
ArrayList al = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
// 1.打印集合
sop(al);

// 2.获取集合长度size()
sop(al.size());

// 3.删除元素,打印改变后的集合remove()
al.remove("java02");
sop(al);
// 清空集合clear()
//al.clear();

// 4.判断元素contains(),isEmpty()
sop("java03是否存在"+al.contains("java03"));
sop("集合是否为空"+al.isEmpty());

ArrayList al2 = new ArrayList();
al2.add("java05");
al2.add("java06");
al2.add("java03");
al2.add("java04");

// 5.取交集
al.retainAll(al2);// 取交集,结果保存在al中
sop("al:"+al);
sop("al2:"+al2);
//结果:
//al:[java03, java04]
//al2:[java05, java06, java03, java04]

// 6.移除交集
al.removeAll(al2);
sop("al:"+al);
sop("al2:"+al2);
//结果
//al:[]
//al2:[java05, java06, java03, java04]

// 7.添加集合
al.addAll(al2);
sop("al:"+al);
sop("al2:"+al2);

al.add("java01");
// 8.判断是否包含一个集合
sop("al是否包含al2中所有元素:"+al.containsAll(al2));
al.remove("java03");
sop("al是否包含al2中所有元素:"+al.containsAll(al2));

// 9.迭代iterator() 用于取出集合中的元素
Iterator it = al.iterator();
while(it.hasNext()){
sop(it.next());
}
或者如下写法:执行完毕,释放it
/*
for(Iterator it = al.iterator();it.hasNext();){
sop(it.next());
}
*/
//每个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容判断和取出,那么可以将这些共性抽取,形成了一个接口,Iterator,如何获取集合的取出对象呢?通过一个对外提供的方法,iterator()。

}
public static void sop(Object obj){
System.out.println(obj);
}
}
add方法的参数类型是Object,以便于接收任意类型对象
集合中存储的都是对象的引用(或者叫地址)

二、List集合共性方法
特有方法,凡是可以操作角标的方法都是该体系特有的方法
1.
add(index, element);
addAll(index, Collection);
2.
remove(index);
3.
set(index, element);
4.
get(index);
subList(from, to);
listIterator();
List集合特有的迭代器,是Iterator的子接口,
在迭代时,不可以通过集合对象的方法操作集合中的元素
以为会发生ConcurrentModificationException异常
所以在迭代时,只能用迭代器的方法操作元素,可是Iterator的方法时有限的,只能对元素进行判断,取出,删除的操作,如富哦想要其他的操作,如添加,修改等,就需要使用其子接口ListIterator,该接口只能通过List集合的ListIterator方法获取

eg:
import java.util.*;
class ListDemo
{
public static void main(String[] args){
ArrayList al = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java03");

sop("原集合是:"+al);
// 原集合是:[java01, java02, java03]

// 1.在指定位置添加元素
al.add(1,"java09");
sop("1.新集合是:"+al);
// 1.新集合是:[java01, java09, java02, java03]

// 2.删除指定位置元素
al.remove(2);
sop("2.新集合是:"+al);
// 2.新集合是:[java01, java09, java03]

// 3.修改元素
al.set(2,"java07");
sop("3.新集合是:"+al);
// 3.新集合是:[java01, java09, java07]

// 4.通过角标获取元素
sop("4.get(1):"+al.get(1));
// 4.get(1):java09

// 5.获取所有元素
for(int x = 0; x < al.size(); x++){
sop("5.al("+x+")"+al.get(x));
}
// 5.al(0)java01
// 5.al(1)java09
// 5.al(2)java07 

// 6.迭代方式
Iterator it = al.iterator();
while(it.hasNext()){
sop("6.next:"+it.next());
}
// 6.next:java01
// 6.next:java09
// 6.next:java07

// 7.获取元素位置
sop("7.index="+al.indexOf("java01"));
// 7.index=0

// 8.获取指定范围的元素
List sub = al.subList(1,3);
sop("sub="+sub);
// 8.sub=[java09, java07]

// 9.列表迭代器,在迭代过程中准备添加或者删除元素
sop("9.原集合al="+al);
ListIterator li = al.listIterator();
while(li.hasNext()){
Object obj = li.next();
if(obj.equals("java09"))
//li.add("java08"); // 增加,结果在java09后面增加java08
li.set("java0009");// 修改,结果将java09修改为java0009
}
sop("9.改变后al="+al);
// 9.原集合al=[java01, java09, java07]
// 9.改变后al=[java01, java0009, java07]


// 10.ListIterator的hasPrevious(),hasNext()方法
hasPrevious()逆向遍历,判断前面是否有元素,配合previous()使用
hasNext()正向遍历,判断后面是否有元素,配合next()使用
}
public static void sop(Object obj){
System.out.println(obj);
}
}

ArrayList 与 Vector 区别?
1. 底层结构都是数组结构,且功能基本相同
2. Vector 1.0版本
ArrayList 1.2版本开始出现,替代Vector
3. ArrayList 线程不同步,多线程时可加锁控制
Vector 线程同步
4. 都是可变长度数组,定义时,默认长度为10
ArrayList 超过长度,50%延长
Vector 超过长度,100%延长

枚举
是Vector特有的取出方式
枚举和迭代功能是一样的
因为枚举的名称以及方法的名称都过长,所以被迭代器取代了
eg:
class VectorDemo
{
public static void main(String[] args){
Vector v = new Vector();
v.add("java001");
v.add("java002");
v.add("java003");
Enumeration en = v.elements();
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
System.out.println(v);
}
}
结果:
java001
java002
java003
[java001, java002, java003]

LinkedList
特有方法:
addFirst(); // 在首位增加元素
addLast(); // 在末尾增加元素
getFirst(); // 获取首位元素
getLast(); // 获取末尾元素
removeFirst(); // 移除首位元素
removeLast(); // 移除末尾元素
上面get和move的方法,如果集合为空,则抛出异常NoSuchElementException
在JDK1.6出现了替代方法,如果集合中没有元素,返回null
offerFirst();
offerLast();
peekFirst();
peekLast();
pollFirst();
pollLast();

eg:
class LinkedListDemo
{
public static void main(String[] args){
LinkedList link = new LinkedList();
link.addFirst("java001");
link.addFirst("java002");
link.addFirst("java003");

System.out.println("link:"+link);
// link:[java003, java002, java001]

link.addLast("java004");
link.addLast("java005");
System.out.println("link:"+link);
// link:[java003, java002, java001, java004, java005]

System.out.println("link.getFirst():"+link.getFirst());
System.out.println("link.getLast():"+link.getFirst());

System.out.println("link.getLast():"+link.removeFirst());
System.out.println("link:"+link);

System.out.println("link.getLast():"+link.removeLast());
System.out.println("link:"+link);
}
}

LinkedList练习
--使用LinkList模拟一个堆栈或者队列数据结构
--堆栈:先进后出
--队列:先进先出
class LLDemo
{
private LinkedList link;
LLDemo(){
link = new LinkedList();
}
public void myAdd(Object obj){
link.addFirst(obj);
}
public Object myGet(){
return link.removeLast();//队列,先进先出
//return link.removeFirst();//堆栈,先进后出
}
public boolean isNull(){
return link.isEmpty();
}
}
class LinkedListTest
{
public static void main(String[] args){
LLDemo lld = new LLDemo();
lld.myAdd("java001");
lld.myAdd("java002");
while(lld.isNull()){
System.out.println(lld.myGet());
}
}
}

ArrayList
练习1
--去除ArrayList中的重复元素
class ArrayListTest
{
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add("java001");
list.add("java002");
list.add("java001");
list.add("java002");
list.add("java001");
list.add("java003");

sop("oldlist:"+list);

list = singElements(list);
sop("newlist:"+list);

}
public static void sop(Object obj){
System.out.println(obj);
}
public static ArrayList singElements(ArrayList list){
ArrayList newList = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
if(!newList.contains(obj))
newList.add(obj);
}
return newList;
}
}
result:
oldlist:[java001, java002, java001, java002, java001, java003]
newlist:[java001, java002, java003]

练习2
将自定义对象作为元素存到ArrayList集合中,并去除重复元素
同姓名同年龄视为同一个人
class Person{
private String name;
private int age;
Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;//多态转型
return this.name.equals(p.getName()) && this.age==p.getAge();//转成同种类型后比较
}
// 覆写Object的equals方法
// 因为contains方法实际调用的是底层的equals方法,而Object中的方法比较的是对象,没有具体的比较条件
}

三、Set
set集合的功能和Collection功能是一致的
--HashSet :底层结构是哈希表,线程是非同步的
HashSet是如何保证元素唯一性呢?
通过元素的两个方法hashCode()和equals()来完成
如果元素的HashCode值相同,才会判断equals是否为true
如果元素的HashCode值不同,不会调用equals()
而正常新对象都有自己的HashCode,都不相同,所以一般覆写hashCode方法,自定义哈希值
例如上面Person类为例
public int hashCode(){
return name.hashCode()+age*39; //避免计算后哈希值相同,同时注意计算结果超过Int的最大值
}


注意:对于判断元素是否存在,以及删除等操作,用的方法是元素的hashCode和equals方法

--TreeSet :可以对set集合中的元素进行排序
需求:往TreeSet集合中存储自定义对象学生,想按照学生的年龄进行排序
class Student implements Comparable // 强制让学生具有比较性
{
private String name;
private int age;
Student(String name, int age){
this.name = name;
this.age = age;
}
public int compareTo(Object obj){// 覆写方法
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj;
if(this.age>s.age)
return 1;
if(this.age==s.age){
return this.name.compareTo(s.name);//String类已经实现了Comparable
}
return 0;
return -1;
}
}

排序时,当主要条件相同时,一定要判断一下次要条件

TreeSet :底层数据结构是二叉树
保证元素唯一性的依据:compareTo方法,return 0
排序的第一种方式:让元素自身具有比较性,元素需要实现coparable接口,覆盖compareTo方法,此方式也成为元素的自然顺序,或者叫做默认顺序

排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性
在集合初始化时,就有了比较方式
定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数
class MyCompare implements Comparator
{
public int compare(Object o1, Object o2){
Student s1 = (Student)o1;
Student s2 = (Student)o1;
int num = s1.getName().compareTo(s2.getName());
if(num==0){
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}

当两种排序都存在时,以比较器为主

比较器的实现,定义一个类,实现Comparator,覆写compare方法
TreeSet练习
按照字符串长度排序
class TreeSetTest
{
public static void main(String[] args){
TreeSet ts = new TreeSet(new StrLenComparator());
ts.add("bdj");
ts.add("acjf");
ts.add("aaa");
ts.add("bdef");

Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next())
}
}
}
class StrLenComparator implements Comparator
{
public int compare(Object o1, Object o2){
String s1 = (String)o1;
String s2 = (String)o1;

int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
}

改成匿名内部类的格式如下:
class TreeSetTest
{
public static void main(String[] args){
TreeSet ts = new TreeSet(new Comparator(){
public int compare(Object o1, Object o2){
String s1 = (String)o1;
String s2 = (String)o1;

int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
});
ts.add("bdj");
ts.add("acjf");
ts.add("aaa");
ts.add("bdef");

Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next())
}
}
}

泛型
JDK1.5之后出现的新特性,用于解决安全问题,是一个安全机制
好处:
1.将运行时期出现问题ClassCastException,转移到了编译时期
2.避免了强制转换的麻烦
泛型类
class Utils<QQ>
{
private QQ q;
public void setObject(QQ q){
this.q = q;
}
public QQ getObject(){
return q;
}
}

当类中要操作引用数据类型不确定的时候,早期定义Object来完成扩展,现在用泛型类来完成扩展

泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的类型后,所有要操作的类型就已经固定了,如:
class Demo<T>
{
public void show(T t){
System.out.println("show:"+t);
}
}

改进上面的限制,将泛型定义在方法上,如:
class Demo
{
public <T> void show(T t){
System.out.println("show:"+t);
}
}
Demo d = new Demo();
d.show("lalala");
d.show(11);

特殊之处:
静态方法不可以访问类上定义的泛型
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上
class Demo<T>
{
public static <W> void method(W w){
System.out.println("method:"+w);
}
}

泛型定义在接口上
interface Inter(T){
void show(T t);
}
class InterImpl implements Inter<String>{
public void show(String t){
System.out.println("show:"+t);
}
}
class InterImpl<T> implements Inter<T>{
public void show(T t){
System.out.println("show:"+t);
}
}

泛型限定
ArrayList<String> al = new ArrayList<String>();
al.add("abc");
ArrayList<Integer> all = new ArrayList<Integer>();
all.add(123);
printColl(al);
printColl(all);

public static void printColl(ArrayList<?> al){
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next() );
}
}

public static void printColl(ArrayList<? extends Person> al){
Iterator<? extends Person> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next() );
}
}
问号"?"为通配符,也可以理解为占位符
泛型的限定:
? entends E :可以接收E类型或者E的子类型
? super E :可以接收E类型或者E类型的父类型

eg:
class Student implements Comparable<Person>
{
public int compareTo(Person s){
this.getName();
}
}
class Comp implements Comparator<Student>
{
public int compare(Student s1, Student s2){
return s1.getName().compareTo(s2.getName());
}
}或者
class Comp implements Comparator<Person> //? super E
{
public int compare(Person s1, Person s2){
return s1.getName().compareTo(s2.getName());
}
}

TreeSet<Student> ts = new TreeSet<Student>(new Comp());
ts.add(new Student("abc1"));
ts.add(new Student("abc2"));
ts.add(new Student("abc3"));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值