黑马程序员——Java基础知识(集合框架(上))

时间:2022-03-25 12:00:23

集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。

接口:即表示集合的抽象数据类型。接口提供了让我们对集合中所表示的内容进行单独操作的可能。 实现:也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。 算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法,例如查找、排序等。这些算法通常是多态的,因为相同的方法可以在同一个接口被多个类实现时有不同的表现。事实上,算法是可复用的函数。 java中集合类的关系图如下:

由于数据结构的不同,也就有不同的集合,集合也可以叫做容器。

黑马程序员——Java基础知识(集合框架(上))

数组与集合的不同点:

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


Collection是集合框架中的常用接口:

collection有一下两个接口:
|--List: 元素是有序的,元素可以重复。因为该集合体系有索引
|--Set: 元素是无
的,元素不可以重复

一、Collection定义了集合框架的共性功能。
1,添加
add(e);
addAll(collection);
2,删除
remove(e);
removeAll(collection);
clear();
3,判断。
contains(e);
isEmpty();
4,获取
iterator();
size();
5,获取交集。
retainAll();
6,集合变数组。
toArray();

注意:add方法的参数类型是Object。以便于接收任意类型对象。
集合中存储的都是对象的引用(地址)

二、迭代器

什么是迭代器呢?
其实就是集合的取出元素的方式。每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取。迭代器就是这种共性的取出方式,它能会直接访问集合中的元素。所以将迭代器通过内部类的形式来进行描述。通过容器的iterator()方法获取该内部类的对象。

迭代的常见操作

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

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

        remove();//移除

注:在迭代时循环中next调用一次,就要hasNext判断一次。

迭代的两种方式:

第一种方式:这种方式比较优化,运行结束即释放内存

                for(Iterator it = a.iterator();iter.hasNext();  )

                {

                           System.out.println(it.next());

                }

       第二种方式:

                 Iterator  it = a.iterator();

                while(iter.hasNext())

               {

                           System.out.println(iter.next());

               }

三、List

|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList: 底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector: 底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。


List:特有方法。凡是可以操作角标的方法都是该体系特有的方法。
增加
add(index,element);//指定位置添加元素
addAll(index,Collection);//在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素
删除
remove(index);//移除指定位置元素
修改
set(index,element);//修改指定位置元素
查询
get(index)://获取index角标元素
subList(from,to);//获取部分对象元素

List集合特有的迭代器:

listIterator();
int indexOf(obj)://获取元素第一次出现的位置,如果没有则返回-1
ListIterator listIterator();

ListIterator是Iterator的子接口。

在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。List集合判断元素是否相同,依据是元素的equals方法。


四、Vector:

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

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

//示例

Enumeration en = v.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}

LinkedList:

LinkedList:特有方法:
1、添加
addFirst();//从开头添加元素
addLast()
;//从结尾添加元素
2、查询
getFirst();
getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementExcepti
on异常
3、删除
removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementExcepti
on异常

在JDK1.6出现了
以上的替代方法。
1、增加
offerFirst();
offerLast();
2、查询
peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。
3、删除
pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null


/*
使用LinkedList模拟一个堆栈或者队列数据结构。

堆栈:先进后出
队列:先进先出
*/

import java.util.*;
class DuiLie
{
private LinkedList link;

DuiLie()
{
link = new LinkedList();
}
//添加元素到开头位置
public void myAdd(Object obj)
{
link.addFirst(obj);
}
//获取开头元素,并删除
public Object myGet()
{
return link.removeFirst();
}
//获取结尾的元素,并删除
public Object myGet_1()
{
return link.removeLast();
}
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");
dl.myAdd("java04");
//先进后出
while(!dl.isNull())
{
System.out.println(dl.myGet());
}
/*//先进先出
while(!dl.isNull())
{
System.out.println(dl.myGet());
}
*/

}
}


五、Set:

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
|--TreeSet:可以对Set集合中的元素进行排
序,底层数据结构是二叉树

Set集合的基本功能和Collection是一致的。


HashSet是如何保证元素唯一性的呢?
它是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

//示例

import java.util.*;
class HashSetDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
HashSet hs = new HashSet();
//不能存入同样的元素:唯一性
sop(hs.add("java01"));//true
sop(hs.add("java01"));//false 判断唯一性
hs.add("java03");
hs.add("java04");
hs.add("java05");

for (Iterator it = hs.iterator(); it.hasNext(); )
{
sop(it.next());//无序打印
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public boolean equals(Object obj) //判断contains、删除remove、底层都用了equals,注意。
{
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;
}
}


TreeSet:

|--TreeSet:可以对Set集合中的元素进行排序,底层数据结构是二叉树


TreeSet:保证元素唯一性的依据是:CompareTo方法return返回值大小;

TreeSet排序的第一种方式:让元素自身具备比较
性,元素需要实现Comparable接口,覆盖compareTo方法这种方式也成为元素的自然顺序,或者叫做默认顺序
TreeSet的第二种排序方
式:当元素自身不具备比较性时,或者具备的比较性不是所需要的这时就需要让集合自身具备比较性在集合初始化时就有了比较方式(构造函数)

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

class TreeSetTest 
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StrLenComparator());

ts.add("abcdef");
ts.add("sdfew");
ts.add("adrhjk");
ts.add("effhy");
ts.add("sdf");

for(Iterator it = ts.iterator(); 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)o2;
int num =new Integer(s1.length()).compareTo(new Integer(s2.length()));//判断s1的长度和s2的长度是否相等在转成整数类
if(num == 0)
return s1.compareTo(s2);//当字符串长度相等的时候判断字符串是否一样
return num;
}
}