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

黑马程序员--集合(一)

2015-11-07 18:07 495 查看
黑马程序员--集合(一)

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

集合类

一、概述

1、集合类:储存对象最常用的方式的方式之一。数据多了用对象存,对象多了用集合存。

集合类的特点:只用于存储对象,长度可变,可存储不同类型的对象。

PS:

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

数组长度固定,且只能存相同类型的对象。

集合长度可变;数组可储存基本数据类型,集合只能储存对象。

2、集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。

任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。

集合框架的优点:

简化程序设计;提高程序效率;提高API的使用效率;提高代码复用性。

集合框架的构成和分类:



二、Collection接口

框架的顶层-->Collection接口:

1、常见方法:

1.1添加:

boolean add(Object obj);

boolean addAll(Collection coll);

1.2删除

boolean remove(Object obj);

boolean removeAll(Collection coll);

void clear();

1.3判断

boolean contains(Object obj);

boolean containsAll(Collection coll);

boolean isEmpty();判读集合中是否有元素。

1.4获取

int size();

Iterator iterator():返回迭代器接口。

迭代器接口:对所有Collection容器进行元素取出的公共接口。

具体方法:

hasNext():若仍有元素可迭代,则返回true。

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

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

PS:

由于不同集合数据结构不同,造成每一个集合存取的方式可能不同。一般当我们需要多个动作(判断、取出)

才能完成一个动作的取出时,我们就将取出动作封装成一个对象。同时,因为其操作元素在集合中,

通过定义内部类,取出方式就可以直接访问集合内容元素。同时,我们将内部类都符合的取出方式规则定义在Iterator接口中,

通过iterator()方法获取。

1.5其他

boolean retainAll(Collection coll):取交集

Object toArray():将集合转成数组

import java.util.*;
/*
1.add方法的参数类型是Object.以便于接收任意类型对象。
2.集合中存储的都是对象的引用(地址)。
3.集合变数组。
Collection接口中的toArray方法。
3.1指定类型的数组到底要定义多长?
当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新的数组。
当指定类型的数组长度大于集合的size,就不会创建一个新的数组。而是使用传递进来的数组。
所以创建一个刚刚好的数组内存处置最优。
3.2为什么要将集合变数组?
当不需要对集合元素增删时,可限定对元素的操作。因为数组长度固定。
*/
class CollectionDemo
{
public static void main(String[] args)
{
base_method();
other_method();
}
public static void base_method()
{
Collection col1 = new ArrayList();

//添加元素
col1.add("java01");
col1.add("java02");
col1.add("java03");
sop("col1添加:"+col1);

Collection col2 = new ArrayList();
col2.addAll(col1);
sop("col2添加:"+col2);

//删除元素
sop("删除java02:"+col1.remove("java02"));
col1.clear();
sop("清空后集合"+col1);

//判断元素
sop("java03是否存在:"+col1.contains("java03"));
sop("col2是否为空?"+col2.isEmpty());

//获取
sop("获取col2中元素个数:"+col2.size());
//获取迭代器,取出集合中的元素。接口性引用只能指向自己的子对象。it随for循环结束而释放,更节省内存。
for(Iterator it = col2.iterator();it.hasNext();)
{
System.out.print(it.next()+" ");
}
System.out.println();

Collection col3 = new ArrayList();

col3.add("java02");
col3.add("java05");

sop("col2:"+col2);

//取交集,去除交集
col3.retainAll(col2);
sop("取交集:"+col3);

col3.removeAll(col2);
sop("移除相同元素:"+col3);
}
public static void other_method()
{
Collection<String> col4 = new ArrayList<String>();

col4.add("abc1");
col4.add("abc2");
col4.add("abc3");

//将集合转成数组
String[] arr = col4.toArray(new String[col4.size()]);

sop("集合转数组:"+Arrays.toString(arr));
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



2、List、Set接口



2.1 List接口

2.1.1 List常见方法:

这些方法有一个共性特点:都可以操作角标。

2.1.1.1 添加

void add(index,element);

void addAll(index,Collection);

2.1.1.2 删除

Object remove(index);

2.1.1.3 修改

Object set(index,element);

2.1.1.4 获取

Object get(index);

int indexOf(object);

int lastIndexOf(object);

List subList(form,to);//展现列表

import java.util.*;
class ListDemo
{
public static void main(String[] args)
{
base_method();
}
public static void base_method()
{
List li = new ArrayList();

//添加元素
li.add("java01");
li.add("java03");
li.add("java03");

sop("添加元素:"+li);

//删除指定位置的元素
li.remove(2);
sop("被删除后的集合:"+li);

//修改元素
li.set(1,"java02");
sop("被修改后的集合"+li);

li.add(2,"java02");
sop("定点添加:"+li);

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

//获取所有元素
for(int x=0;x<li.size();x++)
{
System.out.print("li("+x+")="+li.get(x)+" ");
}
System.out.println();

for(Iterator it = li.iterator();it.hasNext();)
{
System.out.print("next:"+it.next()+" ");
}
System.out.println();

//通过indexOf获取对象的位置
sop("index="+li.indexOf("java02"));
sop("lastIndexOf:"+li.lastIndexOf("java02"));

List sub = li.subList(0,3);
sop("sub"+sub);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



2.1.1.5 ListIterator接口

ListIterator接口是Iterator的子接口。它是List集合特有的迭代器。它只能通过listIterator()方法获取。

Iterator方法只能对元素进行判断、取出、删除的操作,当迭代器需要增加元素等操作时,必须通过集合的方法,

这是会出现并发访问异常,存在安全隐患。ListIterator接口扩展了Iterator接口功能。避免了混合使用集合问题。

ListIterator接口常见方法:

add();

hasNext():正向遍历;

hasPrevious():逆向遍历;

next():返回列表中下一个元素;

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

remove():移除元素;

set():替换。

//获取数据的方法有两种:迭代器和集合,当两种方式混合使用时,会发生-->并发访问异常。
import java.util.*;
class ListDemo2
{
public static void main(String[] args)
{
iterator_method();
}
public static void iterator_method()
{
//演示列表迭代器
List li = new ArrayList();
//添加元素
li.add("java01");
li.add("java02");
li.add("java03");
sop("li="+li);

//本例中,li是集合;it是迭代器。当两种方式访问同一数据时,会存在安全隐患。
for(Iterator it = li.iterator();it.hasNext();)
{
//因为要判断的it.next()要==java02,所以obj(即it)为java01。
Object obj = it.next();
if(obj.equals("java02"))
//因为迭代器只有移除方法,没有添加,所以需要借助集合的add()方法。
li.add("java008");
it.remove();
//会输出java01,因为remove只移除了引用,对象还存在。
sop("obj="+obj);
sop("li="+li);
}
sop(li);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



/*
List定义了自己的迭代器接口:ListIterator()。避免Itetator接口中可使用方法较少,混合使用集合和迭代器的问题。
ListIterator是Iterator的子接口。该接口只能通过List集合的listIterator方法获取。
*/
import java.util.*;
class ListDemo3
{
public static void main(String[] args)
{
iterator_method();
}
public static void iterator_method()
{
//演示列表迭代器
List li = new ArrayList();
//添加元素
li.add("java01");
li.add("java03");
li.add(1,"java02");
sop("li="+li);

//其可以增、改、查的原因是它带角标。
ListIterator lit = li.listIterator();

//判断迭代前有没有元素
sop("hasPrevious():"+lit.hasPrevious());
while(lit.hasNext())
{
Object obj = lit.next();

//替换元素
if(obj.equals("java02"))
lit.set("java007");
}
//判断迭代后有没有元素
sop("hasNext():"+lit.hasNext());
sop("hasPrevious():"+lit.hasPrevious());
sop("li="+li);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



2.1.2List分类:

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

|--Vector:底层是数组数据结构。线程同步。Vector生成20容量的数组,但是较浪费空间。被ArrayList替代。

|--ArrayList:底层是数组数据结构。线程不同步。特点:查询块;增删慢。可变长度数组:超过10后,生成15容量的数组。

|--LinkedList:底层使用的链表数据结构。特点:增删快;查询慢。



import java.util.*;
class LinkedListDemo
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();

//先存的为尾
link.addFirst("java01");
link.addFirst("java02");
link.addFirst("java03");

sop("link="+link);

sop("获取尾元素:"+link.getFirst());

sop("获取头元素:"+link.getLast());

sop("移除尾元素:"+link.removeFirst());

sop("link="+link);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



JDK1.6后方法:

/*
使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出  如同杯子。
队列:先进先出  如同水管。
*/

import java.util.*;
class DuiLie
{
private LinkedList link;
DuiLie()
{
link = new LinkedList();
}
//先入的为尾
public void myAdd(Object obj)
{
link.offerFirst(obj);
}
//获取并删除先存入的元素
public Object myGet()
{
return link.pollLast();
}
public boolean isNull()
{
return link.isEmpty();
}
}
class LinkedListTest
{
public static void main(String[] args)
{
DuiLie dl = new DuiLie();

dl.myAdd("java01");
dl.myAdd("java02");
dl.myAdd("java03");

while(!dl.isNull())
{
System.out.print(dl.myGet()+" ");
}
System.out.println();
}
}
运行结果:



PS:

Enumeration(枚举):是Vector特有的取出方式。枚举和迭代功能一样。

2.2 Set接口

Set接口中元素不可以重复,无序(存入和输出顺序不一定一致)。它的方法和Collection一致。



HashSet保证元素唯一性原理:判断元素的hashCode值是否相同。

如果元素的哈希值相同,才会判断对象内容是否相同。

PS:

1、判断元素是否存在,以及删除等操作,HashSet依赖的方法是元素的hashCode和equals方法;

而ArrayList只依赖equals方法。TreeSet保证元素唯一性的依据compareTo方法。

原因:数据结构不同,所依赖方法也不一样。

2、让HashSet无序变有序,可使用LinkedHashSet。

import java.util.*;
/*
通过hashSet集合判断Person对象是否相同。姓名和年龄相同视为重复元素。
*/
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//复写hashCode()
public int hashCode()
{
//看hashCode的调用记录
System.out.println(this.name+"....hashCode()");
//字符串name有自己的hashCode值,排除和相同的情况
return name.hashCode()+age*37;
}
//复写equals
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;

//向下转型。因为要使用Person自己的方法。
Person p = (Person)obj;
System.out.println(this.name+"...equals.."+p.name);

return this.name.equals(p.name) && this.age == p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashSetTest
{
public static void main(String[] args)
{
HashSet hs = new HashSet();

hs.add(new Person("a1",11));
hs.add(new Person("a2",12));
hs.add(new Person("a3",13));
hs.add(new Person("a4",13));

for(Iterator it = hs.iterator();it.hasNext();)
{
Person p = (Person)it.next();
sop(p.getName()+"...."+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:



2.2.1TreeSet排序

a 元素的自然顺序(默认顺序)。让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。

/*
需求:往TreeSet集合中存储自定义对象学生。按照学生的年龄进行排序。

注意:排序时,当主要条件相同时,一定判断一下次要条件。
Comparable是一个接口,用于强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
compareTo():比较此对象与指定对象的顺序。返回负数、零、整数。
ClassCastException:类型转换异常。
*/
import java.util.*;
//Comparable接口强制让学生具备比较性
class Student implements Comparable
{
private String name;
private int age;

Student(String name,int age)
{
this.name = name;
this.age = 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);

int temp = this.age-s.age;

//有具体返回值可以用三元运算符,年龄相同,再按名字排。
return temp==0?this.name.compareTo(s.name):temp;
}

public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();

//所存元素必须具备比较性, TreeSet()才能排序。
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi04",20));
ts.add(new Student("lisi02",19));
ts.add(new Student("lisi01",20));

for(Iterator it = ts.iterator();it.hasNext();)
{
Student stu = (Student)it.next();//向下转型。
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
运行结果:



b 自定义比较器。让集合自身具备比较性:定义一个类,实现Comparator接口,覆盖compare方法。将该类对象

作为参数传递给TreeSet集合的构造函数。这种方法适用于:元素自身不具备比较性或不具备自己所需的比较性。

当两种方式都存在时,以比较器为主。

/*
练习:按照字符串长度排序。
自定义比较器:元素自身不具备比较性或不具备自己所需的比较性。
*/
import java.util.*;
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StrLenComparator());

ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("z");
ts.add("hahhaha");

for(Iterator it = ts.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}
//实现Comparator接口,覆盖compare方法。
class StrLenComparator implements Comparator
{
public int compare(Object o1,Object o2)
{
String s1 = (String)o1;
String s2 = (String)o2;

//String类的compareTo方法
int num =new Integer(s1.length()).compareTo(new Integer(s2.length()));

if(num==0)
//主要条件符合,判断次要条件
return s1.compareTo(s2);
return num;
}

}
运行结果:

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