**
Collection
**
Collection接口定义了一个集合的抽象形式,其中包括两个子接口——List接口与Set接口。List接口的实现类包括Vector,ArrayList与LinkedList。Set接口的实现类包括TreeSet,HashSet,LinkedHashSet。
我们先来关注List的接口的实现类们。
ArrayList
首先是ArrayList这个实现类(我们不讨论Vector是因为Vector是最早出现的java中的集合,直到现在已经被基本代替不在使用它了。
ArrayList的底层是一个数组结构,查询快,增删慢,并且ArrayLis的长度可以改变。
我们先来创建一个ArrayList对象
ArrayList<String> list=new ArrayList<>();
//<E>代表泛型,也就是在一个list中全部是统一的某种类型,且只能是引用类型。这里使用了String类型,也就是这个co集合中全部都是String类型的数据
创建完对象来看一下ArrayList的常用方法,一些注释我都写在了代码后面
add方法
//add方法添加往集合中元素
boolean success=list1.add("gfx");
System.out.println("添加gfx是否成功 "+success);
list1.add("zbh");
list1.add("ycj");
list1.add("jyh");
list1.add("xdy");
list1.add("lxl");
System.out.println(list1);
结果
添加gfx是否成功 true
[gfx, zbh, ycj, jyh, xdy, lxl]
get方法
//get方法获取指定位置的元素
String name=list1.get(1);
System.out.println("1号索引位置:"+name);
结果
1号索引位置:zbh
remove方法
//remove方法删除集合中的指定元素并可以返回它
String whoRemoved=list1.remove(5);
System.out.println(list1);
System.out.println("删除的人是:"+whoRemoved);
结果
[gfx, zbh, ycj, jyh, xdy]
删除的人是:lxl
size方法
//size方法可以返回一个集合的元素个数
int size=list1.size();
System.out.println("list1的长度是:"+size);
结果
list1的长度是:5
前面的代码注释中写道,ArrayList里面储存的类型只能是引用类型,但是Java提供了包装类(把基本数据类型包装成类使它变成了引用类型),使得我们在集合中也可以储存整数,字符等数据类型。
大部分基本类型的包装类就是把首字母大写,例如double->Double。但是有两个特殊,int->Integer与char->Character。
ArrayList<Integer> list2=new ArrayList<>();
//正确写法,list2储存整数,Integer是一个引用数据类型
//ArrayList<int> list2=new ArrayList<>();
//错误,int是一个基本数据类型
LinkedList
下面来看List接口的另一个实现类,LinkedList。LinkedList与ArrayList不同的是,它底层是一个链表结构(而不是数组),查询慢,增删快。
因为LinkedList底层是一个链表结构,所以LinkedList类中有许多对首尾的操作。我们来看一下代码
public static void main(String[] args) {
LinkedList<String> link=new LinkedList<>();
//创建了一个LinkedList对象link
//作用于ArrayList的add方法相同
link.add("a");
link.add("b");
link.add("c");
//LinkedList特有方法addFirst
link.addFirst("A");//在集合头部添加一个A
System.out.println(link);
//等效的LinkedList的特有方法还包括:addLast(等效于add方法)与push(等效于addFirst方法)
//LinkedList特有方法getFirst和getLsat
String s1=link.getFirst();//获取集合头部元素
String s2=link.getLast();//获取集合尾部元素
System.out.println(s1);
System.out.println(s2);
//LinkedList特有方法removeFirst与removeLast
String s3=link.removeFirst();//remove了A,等效于pop方法
String s4=link.removeLast();//remove了c
System.out.println(s3);
System.out.println(s4);
System.out.println(link);
}
结果
[A, a, b, c]
A
c
A
c
[a, b]
上面就是List这一类集合的两大实现类了,在我们把注意力转移到Set集合前,我简单介绍一下常用的一些数据结构:
1.栈:先进后出,一个出口(子弹弹夹)
2.队列:先进先出,两个出口(排队安检)
3.数组:查询快,增删慢(因为数组长度固定,所以增删需要一个新数组)
4.链表:查询慢,增删快(查询慢是因为链表不是连续的)
链表分为单向链表(无序)和双向链表(有序)
5.红黑树:趋近于平衡树,查询速度非常快
红黑树必须满足的要求:
1.根结点是黑色的
2.空节点是黑色的
3.红色节点的子女是黑色的
4.任何一个节点到到每一个叶子结点的所有路径上黑色节数目相同
上面是一个非常简略的介绍,数据结构本身就是一门课程,把太多重点放到上面不符合我们日志的核心。
Set
Set的特点:
1.不能存储重复值
2.存储是无序的
3.不能用普通for循环来遍历,只能用Iterator(后面会介绍一下)或者增强for循环
HashSet
HashSet是Set的一个实现类,底层是一个哈希表的结构,我们来看一下使用
HashSet<String> hashset=new HashSet<>();
hashset.add("aaa");
hashset.add("bbb");
hashset.add("ccc");
hashset.add("ddd");
for(String i:hashset)
{
System.out.println(i);
}
long l=hashset.hashCode();//获取哈希值
//哈希值是一个十进制的数字,是系统随机给出来的(是对象的逻辑地址)
System.out.println(l);
结果
aaa
ccc
bbb
ddd
391242
我们看到输入和输出的顺序变了,这正是Set的特点。
LinkedHashSet
LinkedHashSet是一个有序的Set接口的实现类,原因是底层是哈希表加链表,因为多了链表所以保证了有序。
LinkedHashSet<String> linkedhashset=new LinkedHashSet<>();
linkedhashset.add("vvv");
linkedhashset.add("bbb");
linkedhashset.add("nnn");
linkedhashset.add("mmm");
for(String i:linkedhashset)
{
System.out.println(i);
}
long l1=linkedhashset.hashCode();//获取哈希值
System.out.println(l1);
结果
vvv
bbb
nnn
mmm//有序的输出
431955
Collection
在看完了上面Collection的两大接口的多种实现类后,我们最后来看一下正主。
Collection中包括add,remove,contains,isEmpty,size,toArray,clear方法。这些方法是共性的,所以就算用没学过的集合,使用多态的形式也可以使用这些方法。
Collection<String> co=new ArrayList<>();//多态
co.add("乔丹");
co.add("詹姆斯");
co.add("科比");
co.add("邓肯");
co.add("约翰逊");
co.add("拉里伯德");
现在我要遍历这个集合,我们可以怎么办呢?当然,增强for循环可以,但是Iterator(迭代器)也可以。
for(String i:co)
{
System.out.println(i);
}
//增强for循环
System.out.println("===================");
Iterator<String> it=co.iterator();
//Iterator是接口无法直接创建对象。Collection里面的iterator函数返回一个Iterator的实现类。
while(it.hasNext())
{
System.out.println(it.next());
}
结果
乔丹
詹姆斯
科比
邓肯
约翰逊
拉里伯德
===================
乔丹
詹姆斯
科比
邓肯
约翰逊
拉里伯德
两种方式都可以成功的遍历集合。
下面介绍一个工具类Collections的一个有助于提高集合运用效率的方法(Collections是一个工具类,与Collection接口的不同,可以理解成Collection接口的助手)。
//Collections的常用方法:
ArrayList<String> co1=new ArrayList<>();
//addAll,静态方法,类名直接调用
Collections.addAll(co1,"v","b","c");
System.out.println(co1);
//shuffle方法,打乱顺序
Collections.shuffle(co1);
System.out.println(co1);
//第一种sort方法
Collections.sort(co1);
System.out.println(co1);//默认升序sort可以对自定义的类排序,前提是该类实现comparable接口,重写compareto方法
//第二种sort方法
ArrayList<Integer> co2=new ArrayList<>();
Collections.addAll(co2,1,5,23,4);
System.out.println(co2);
Collections.sort(co2,new Comparator<Integer>() {
@Override
public int compare(Integer o1,Integer o2)
{
return o1-o2;//升序,就是前面的参数减去后面的参数
//return o1-o2;//降序,与上面相反
}
});
System.out.println(co2);
结果
[v, b, c]
[c, v, b]
[b, c, v]
[1, 5, 23, 4]
[1, 4, 5, 23]
这次大概就是这么多啦,88。