目录
@ 这篇文章是我学习完Java集合类做的笔记和总结,如果你想认真细读这篇文章,请做好受虐的准备(建议电脑看),因为这篇文章有点长,ヽ(ー_ー)ノ。 如果在看我这篇文章过程中,发现了错误,望指点。
一、什么是集合?
举个例子:当你有很多书时,你会考虑买一个书柜,将你的书分门别类摆放进入。使用了书柜不仅仅使房间变得整洁,也便于以后使用书时方便查找。在计算机中管理对象亦是如此,当获得多个对象后,也需要一个容器将它们管理起来,这个容器就是集合。
集合本质是基于某种数据结构数据容器。常见的数据结构:数组(Array)、集(Set)、队列(Queue)、链表(Linkedlist)、树(Tree)、堆(Heap)、栈(Stack)和映射(Map)等结构。
下面便 一 . 一 介绍:
其中在两大接口中会有框架图,以方便大家学前、学后在大脑里可以形成一个思维导图,也方便大家检查自己对各各知识点的熟悉程度。 注意: 由于在集合中是有一个参数化类型的,所以在下面的代码里我会 指定成Object 。为什么我要指定为Object呢?因为Java中的Object类是所有类的超类。 先涉及一下泛型的定义:集合类 对象 = new 集合类 (); 也可以先前往 四、泛型,了解U•ェ•*U
二、Collection接口
1、集合类中Collection接口的介绍
首先了解一下Collection接口是List、Set、Queue等接口的父接口。 先简单了解一下Collection接口的常用方法吧:
bollean add(Object obj) 向集合添加一个obj元素
void clear() 清空集合中所有元素
boolean isEmpty() 如果此集合为空,则返回turn
int size() 返回此集合中元素个数
如果想了解其他方法可以查询 Java基础类库(API) 这个是个好东西强烈推荐
下面先看看例题演示上面的方法吧:
import java.util.*;
public class TestCollection{
public static void main(String[] args) {
Collection
输出的结果为:
[1000, phone]
2
[1000, phone]
true
需要注意的是,在用Collection创建集合时是以实现类ArrayList的实例和实现类HashSet的实例来当做Collection来使用的。
Collection的简单了解就到这里。
2、List接口
特点:List接口能够精确地控制每一个元素插入的位置,用户可以通过索引来访问集合中指定的元素,List还有一个特点就是元素的存入顺序与取出顺序相一致。
(1)、ArrayList实现类
其中ArrayList(效率高但线程不安全)是List的主要实现类,它是一个数组队列,相当于动态数组。通过下面例题了解:
import java.util.*;
public class TestArrayList{
public static void main(String[] args) {
ArrayList arr = new ArrayList(); //创建ArrayList集合
arr.add(1000); //向集合中添加元素
arr.add("phone");
System.out.println(arr.size()); //打印集合元素的个数
System.out.println(arr.get(0)); //取到并打印集合中指定索引的元素
}
}
打印结果为:
2
1000
虽然ArrayList的查询效率很高,非常适合做大量的查询操作,但不适合大量的增删操作,所以为了解决这一问题就添加了LinkedList实现类
(2)、LinkedList实现类
创建了LinkedList集合后,便可使用以下方法(想了解更多请查找JAVA基础类库):
void add(int index, Object o) 将o插入索引为index的位置
void addFirst(Object o) 将o插入集合的开头
void addLast(Object o) 将o插入集合的结尾
Object removeFirst() 删除并返回集合的第一个元素
Object removeLast() 删除并返回集合的最后一个元素
例题演示上面介绍的方法:
import java.util.*;
public class TestLinkedList{
public static void main(String[] args) {
LinkedList link = new LinkedList(); //创建LinkedList集合
link.add(1000);
link.add("phone");
System.out.println(link);
link.add(1,"charu"); //在索引1的位置,插入
System.out.println(link);
link.addFirst("stu"); //在集合首部添加元素
System.out.println(link);
System.out.println(link.removeLast()); //删除并返回集合的最后一个元素
System.out.println(link);
}
}
结果为:
[1000, phone]
[1000, charu, phone]
[stu, 1000, charu, phone]
phone
[stu, 1000, charu]
由此可见,LinkedList对增加和删除的操作高效且便捷
(3)、迭代器(Iterator)
既然我们已经存储了很多元素,并且也做到了增与删,但我们可不可以遍历打印所以元素呢? 迭代器(Iterator) 它可以
创建了bianli的对象后,可以这样使用迭代器(Iterator)
Iterator i = bianli.iterator(); //获取Iterator对象
while(i.hasNext()){ //hasNext()方法检测是否存在下一个元素
System.out.println(i.next()); //next()方法获取元素,获取条件必须是hasNext()方法判断下一个元素存在,否则停止遍历
}
代码演示:
import java.util.*;
public class TestIterator{
public static void main(String[] args) {
Collection bianli = new ArrayList(); //创建LinkedList集合
bianli.add(2020);
bianli.add("新年快乐");
bianli.add("B站的跨年晚会");
bianli.add("很精彩");
Iterator i = bianli.iterator(); //获取Iterator对象
while(i.hasNext()){ //hasNext()方法检测是否存在下一个元素
System.out.println(i.next()); //next()方法获取元素,获取条件必须是hasNext()方法判断下一个元素存在,否则停止遍历
}
}
}
但迭代器(Iterator)运行过于复杂且性能差,所以尽量别用。
(4)、for each循环
由于迭代器(Iterator)有些复杂,万能的Java便又添加了for each循环,该循环能遍历集合与数组
语法格式:
for(容器中元素类型 临时变量 : 容量变量){ //容量变量指的是1、数组,则填存储数组名。2、集合,则填集合对象
程序语句
}
for each有局限性,因为临时变量,所以只能进行访问,而无法进行修改。
(5)、ListIterator接口
在 迭代器(Iterator) 中存在着无法解决并发执行操作的问题(并发操作:指在宏观上的同一时间内同时执行多个任务),其实就是在迭代器(Iterator)遍历过程(while程序语句里)中给集合添加元素,但由于Iterator接口不能很好地支持并发操作,从而出现运行出错。
在java中为了解决这一问题便提供了,ListIterator接口来解决这一问题
语法格式与迭代器(Iterator)差不多
ListIterator 临时变量 = 对象.listIterator();
(6)、Enumeration接口的古老实现类Vector
其实在没有遍历集合Iterator接口前,很古老的实用类Vector(线程安全但效率低),与Iterator接口类似,下面给大家了解一下Vector类,它提供了elements()方法用于返回Enumeration对象,然后通过Enumeration对象遍历集合中的元素。
格式与介绍其hasMoreElements()、nextElement()两个方法的使用
Enumeration ele = v.elements(); //获得Enumeration对象
while(ele.hasMoreElements()){ //判断ele对象是否仍有元素
Object o = ele.nextElement(); //取出ele的下一个元素
System.out.println(o);
}
Vector是比较古老的集合类,了解一下就好。
当你看到这里,你大概基本了解Collection接口的用法,当你把他们所有的关系写成流程图,你会发它们的关系非常有意思,比如:因为ArrayList集合由于不适合大量增删操作,所以提供了LinkedList实现类来解决这一问题等等,会发现很多的方法都是建立在原来方法的问题上,用另外的方法去解决它。
3、Set接口
(1)、Set的简单介绍和hashSet集合的使用
好,我们继续了解一下Collection的另外一个子接口Set吧!!! Set集合中的元素是无序的、不可重复的。但这里的无序性不等于随机性,无序性指的是元素在底层存储位置是无序的。
Set接口的主要实现类是HashSet和TreeSet。
下面来好好介绍一下吧。HashSet集合(它是按哈希算法来存储集合中的元素的):
下面先了解一下例题代码吧:
import java.util.*;
public class TestHashSet{
public static void main(String[] args) {
Set set = new HashSet (); //创建HashSet集合
set.add(null); //向集合存储元素
set.add(new String("JAVA"));
set.add("程序");
set.add("设计");
set.add("JAVA");
for(Object o : set) { //遍历集合
System.out.println(o);
}
}
}
打印结果:
null
JAVA
设计
程序
可以看出按照存入顺序应该是先打印 "程序" 再打印 "设计" 的,但结果不是,这证明了HashSet存储的无序性;其中我们存储了两次"JAVA"但打印的只有一次,同样也说明了HashSet元素的不可重复性。
(2)、哈希的简单介绍
可能有人会问为什么不可重复呢?
这是因为HashSet底层是哈希表结构,可能有人不懂“哈希”是什么?那我就简单说一下吧。
哈希和哈希算法,哈希也称散列,哈希表是一种与数组、链表等不同的数据结构,与他们需要不断的遍历比较来查找的办法,
哈希表设计了一个映射关系f(key)= address,根据key来计算存储地址address,这样可以1次查找,f既是存储数据过程中
用来指引数据存储到什么位置的函数,也是将来查找这个位置的算法,叫做哈希算法。
还是不懂!??那好吧,举个栗子
你在家里忘记了指甲刀放在哪里,通常要在你家所有抽屉中顺序寻找,直到找到,最差情况下,有N个抽屉,
你就要打开N个抽屉。这种存储方式叫数组,查找方法称为「遍历」。
而哈希就不一样了,所有物品分门别类放入整理箱,再将整理箱编号,比如1号放入针线,2号放入证件,3号放入细软。这种存储和查找方式称为「哈希」,
如果这个时候要查找护照,你不许要再翻所有抽屉,直接可在2号整理箱中获取,通常只用一次查找即可,如何编号整理箱,称为哈希算法。
因为hashCode()是算出一个值后,元素然后去找集合的位置,如果该位置没有元素,则直接存入;但如果该位置有元素,则用equals()来 判断是否相同,相同则不存储,否则在该位置上存储两个元素(一般不可能重复),所以在一个自定义的对象想正确存入HashSet集合时,那么应该重写自定义对象的 hashCode() 和 equals()方法。
你是不是懵了,因为在刚才例题代码里,不也没有重写吗?为什么还是能正常工作?那是因为String类会自动重写hashCode()和equals()方法。
给你看看如果我不用String会是什么情况呢?
import java.util.*;
public class TestHashSet{
public static void main(String[] args) {
Set set = new HashSet();
set.add(null);
set.add(new People("JAVA")); //没有使用String
set.add("程序");
set.add("设计");
set.add("JAVA");
for(Object o : set) {
System.out.println(o);
}
}
}
class People{
String name;
int age;
public People(String name) {
this.name = name;
}
public String toString() {
return name ;
}
}
打印结果为:
null
JAVA
JAVA
设计
程序
结果很明显一样是都打印了,那要解决这一问题要怎么做呢? 要想解决这一问题,只需要在People类中添加:
public int hashCode(){
通过计算(因为哈希算法可以随意设计,想怎么算都可以),返回对象的哈希值
}
public boolean equals(Object obj){
与各各不同类型的对象判断是否相同,返回为false时,则存储
}
就可以了;HashSet集合就说到这里。
(3)、TreeSet集合
TreeSet底层是用自平衡的排序二叉树实现的,所以它既能保证元素的唯一性,又可以对元素进行排序。还提供了一些特有的方法:
import java.util.*;
public class TestTreeSet{
public static void main(String[] args) {
TreeSet tree = new TreeSet();
tree.add(1);
tree.add(7);
tree.add(18);
System.out.println(tree); //打印集合
System.out.println(tree.first()); //打印集合中第一个元素 last打印最后一个元素
System.out.println(tree.subSet(5, 20)); //打印集合中大于5小于20的元素
System.out.println(tree.headSet(10)); //打印小于10的元素;tailSet大于
}
}
打印结果:
[1, 7, 18]
1
[7, 18]
[1, 7]
其中Tree有两种排序方法:自然排序(默认条件下)与定制排序。 默认排序便不多说,知道有一个方法compareTo(Object obj) 是用来比较元素之间的大小关系,例如:obj1.compareTo(obj2),若方法返回0,则相等;若方法返回正整数,则说明obj1大于obj2;若方法返回负整数,则说明obj1小于obj2.
而定制排序。。。。。emmmm其实就是继承了Comparator接口后,在自定义的子接口中实现一个campare方法,通过返回正负整数还有零,来进行排序, 从而可以达到降序排列等定制排序的目的。
Set接口就说到这里。
4、Queue接口
下面我们来了解Collection接口的最后一个子接口Queue。 Queue用于模拟队列这种数据结构,队列通常是指"先进先出"(FIFO)的容器。
Queue接口有一个PriorityQueue实现类,除此之外,还有一个接口Deque(代表一个"双端队列",双端队列可以同时从两端来添加、删除元素)。Deque可以在队列、栈(该类里的栈包含pop(出栈)、push(入栈)两个方法)中使用,并且提供了实现类ArrayDeque。
(1)、Priority Queue实现类
Priority Queue实现类是一个比较标准的队列,为什么说比较标准?因为保存的元素不是按加入顺序,而是按大小排序。
下面我们来看例题代码:
import java.util.PriorityQueue;
public class TestPriorityQueue{
public static void main(String[] args) {
PriorityQueue pq = new PriorityQueue();
pq.offer(10);
pq.offer(1);
pq.offer(100);
System.out.println(pq);
System.out.println(pq.remove()); //Queue的方法,remove()获取队列头部的元素,并删除该元素
System.out.println(pq);
}
}
打印结果:
[1, 10, 100]
1
[10, 100]
可以看出PriorityQueue比较标准的排序和一些Queue简单的方法(如要了解更多请查阅Java基础类包),注意:PriorityQueue不允许插入null元素
PriorityQueue也有两种排序方式:
1、是自然排序
2、是定制排序
排序要求与TreeSet集合一致
继续了解Queue的另外的接口Deque与ArrayDeque实现类
Deque的方法众多,我便不进行讲解,因为方法的作用与前面所说的差不多,只是方法名不同罢了,其中讲一下ArrayDeque实现类比较特殊的方法,看代码:
import java.util.ArrayDeque;
public class TestArrayDequeStack{
public static void main(String[] args) {
ArrayDeque stack = new ArrayDeque();
stack.push("广东"); //依次将三个元素push入"栈"
stack.push("培正");
stack.push("学院");
System.out.println(stack); //因为是栈的缘故(先进后出),所以存入的元素顺序越靠前,在元素安排上越往后
System.out.println(stack.peek()); //访问第一个元素,但并不将其pop出栈;Queue方法peek()获取队列头部元素,但是不删除该元素。如果队列为空,则返回null
System.out.println(stack);
System.out.println(stack.pop()); //pop出第一个元素
System.out.println(stack);
}
}
打印结果为:
[学院, 培正, 广东]
学院
[学院, 培正, 广东]
学院
[培正, 广东]
从结果可以看出,ArrayDeque有栈的行为("栈"嘛,先进后出,先存入的越往后放),所以当程序中需要所以“栈”这种数据结构时,便可使用。
其中给大家了解一下,虽然Stack也可以作出栈的行为(是以普通方法的形式进行使用的),但尽量避免使用Stack,因为Stack是古老的集合,性能较差。
当然不能忘了ArrayDeque也可以作为队列中使用,只需要在上面的例题代码中,把push修改为offer(boolean offer(Object e)方法将指定元素加入队列尾部。当使用有容量限制的队列时,此方法通常比add(Object e)方法更好)即可。
学习到这里,也把Collection接口的相关知识也了解了,那我问几个问题供你思考。 1、Set接口和List接口有哪些区别? List是有序的可重复的Collection,使用此接口能够精确的控制每个元素插入的位置。能够使用索引高效地访问List中的元素,这类似于Java的数组。Set是一种无序的不包含重复元素的Collection,相比List,它可以更高效地处理增添和删除元素。
2、Iterator(迭代器)和ListIterator接口的区别是什么? Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引等。
3、Enumeration接口和Iterator接口的区别有哪些? Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。
终于把Collection的接口以及子接口List、Set、Queue记录完了。
你以为完了,天真!!!接下来继续记录Map接口吧!??
三、Map接口
先给大家讲一下什么是映射:映射,或者射影,在数学及相关的领域还用于定义函数。函数是从非空数集到非空数集的映射,而且只能是一对一映射或多对一映射。而在这里主要是说每一个指定的键(key)总能找到唯一的、确定的值(value),存在单向一对一关系。
Map与Collection接口是并列存在的,它是用于存储键--值对(key-value)形式的元素,描述了由不重复的键到值的映射。(其中键-值可以是任何引用类型的数据)。因为不可重复性,所以在同一个Map对象所对应的类,必须重写hashCosh()方法和equals()方法。
Map接口的方法有很多,我们了解最常用的两个方法便可:
Object put(Object key, Object value) 功能:将指定的值与此映射中的指定键关联(可选操作)
Object get(Object key) 功能:返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null。
1、HashMap实现类
当然Map的实现类也很多,但最常用的是HashMap类和TreeMap类,接下来详细讲解一下:
HashMap类可以说是Map接口中使用频率最高的实现类,允许使用null键和null值,与前面的HashSet集合一样,不保证映射的顺序,判断两个键(key)是否相同,同样是使用equals()方法,若返回true,则hashCode(哈希)值也相等。
import java.util.*;
public class TestHashMap{
public static void main(String[] args) {
Map map = new HashMap(); //创建HashMap集合
map.put("one", "广东"); //存入元素
map.put("two", "培正");
map.put("three", "学院");
map.put("four", "数科院");
map.put(null, null);
map.put("four", "数据科学与计算机学院"); //体现HashMap集合的不可重复性
System.out.println(map.size()); //打印集合长度
System.out.println(map); //打印集合所有元素
System.out.println(map.get("two")); //取出并打印键为two的值
}
}
打印结果:
5
{null=null, four=数据科学与计算机学院, one=广东, two=培正, three=学院}
培正
相信大家看了上面的例题代码,会发现和HashSet集合一样,结果具有无序性;同时也发现若出现相同的键(key) 时,后添加的值(value)会覆盖先添加的值(value).
(1)、Map的遍历
既然我们集合添加了元素,当然就要一 一遍历出来啦,在之前说了遍历List和for each,但Map遍历方式有所不同,其中遍历方式有两种,先说说第一种吧。 因为Map是关于键与值的关系,所以遍历当然离不开它们,看下面例题代码:
import java.util.*;
public class TestKeySet{
public static void main(String[] args) {
Map map = new HashMap(); //创建HashMap集合
map.put("one", "广东"); //存入元素
map.put("two", "培正");
map.put("three", "学院");
map.put("four", "数科院");
System.out.println(map); //打印集合所有元素
Set keySet = map.keySet(); //获取键的集合,keySet()方法可以获取键的集合
Iterator iterator = keySet.iterator(); //获取迭代器对象
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
System.out.println(key + ":" + value);
}
}
}
打印结果为:
{four=数科院, one=广东, two=培正, three=学院}
four:数科院
one:广东
two:培正
three:学院
相信大家已初步了解第一种遍历,废话不多说,继续第二种遍历,第二种遍历的方式是:先获得集合中所有的映射关系,然后从映射关系获取键和值。看例题代码:
import java.util.*;
import java.util.Map.Entry;
public class TestEntrySet{
public static void main(String[] args) {
Map map = new HashMap(); //创建HashMap集合
map.put("one", "广东"); //存入元素
map.put("two", "培正");
map.put("three", "学院");
map.put("four", "数科院");
System.out.println(map); //打印集合所有元素
Set> entrySet = map.entrySet(); //entrySet()方法:返回此映射所包含的映射关系
Iterator> iterator = entrySet.iterator(); //获取迭代器对象
while(iterator.hasNext()) {
Map.Entry entry = (Entry) iterator.next();
Object key = entry.getKey(); //获取关系中的键
Object value = entry.getValue(); //获取关系中的值
System.out.println(key + ":" + value);
}
}
}
打印结果为:
{four=数科院, one=广东, two=培正, three=学院}
four:数科院
one:广东
two:培正
three:学院
看完两种遍历方式会发现,Map的遍历都是围绕着键(key)和值(value)它们单向一 一对应的关系。但我们前面有说能不用迭代器(Iterator)就不要用,因为这种方式复杂且性能差,所以给大家介绍一下用for each循环的使用:
import java.util.*;
public class Testforeach{
public static void main(String[] args) {
Map map = new HashMap ();
map.put(1,"2020");
map.put(2,"新起点");
map.put(3,"新开始");
Set> entries = map.entrySet(); //entrySet()方法:返回此映射所包含的映射关系,给方式一和方式二用
System.out.println("方式一:"); //第一种:在for each循环中直接打印键与值的关系
for(Map.Entry entry : entries) {
System.out.println(entry);
}
System.out.println("方式二:"); //第二种:与第一种的打印方式不同,是分别获取有关系的键和有关系的值,再打印
for(Map.Entry entry : entries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
System.out.println("方式三:"); //第三种:是获取了键的集合,在打印相对应的值
Set objects = map.keySet();
for(Object object : objects) {
System.out.println(object + ":" + map.get(object));
}
}
}
是否发现for each循环更简单更高效呢。
(2)、子类LinkedHashMap
emmmm遍历就说到这里,下面我们继续来了解HashMap的一个子类LinkedHashMap,其中该类的主要作用是:可以维护Map的迭代器顺序,迭代顺序与键-值对的插入顺序一致。简单地说:就是打印的结果可以不是无序的了,可以按照怎么输入就怎么输出了。来看代码:
import java.util.*;
public class TestLinkedHashMap{
public static void main(String[] args) {
Map map = new LinkedHashMap(); //创建LinkedHashMap集合
map.put("one", "广东"); //添加元素
map.put("two", "培正");
map.put("three", "学院");
map.put("four", "数科院");
System.out.println(map); //打印集合所有元素
}
}
打印结果为:
{one=广东, two=培正, three=学院, four=数科院}
所以只要创建了LinkedHashMap集合就可以打印输入顺序了。
2、TreeMap实现类
下面我们来了解一下,Map第二个常用的类TreeMap吧。
既然前面的TreeSet可以排序,当然这个也可以啦,只需要创建TreeMap集合,便可以默认的进行自然排序,当然在添加元素时要有数据型,不然如何比较排序呢。
有默认当然就要有可以根据自己的需求来排序逻辑,以前面的相同,都是用到int compareTO(T t1, T t2) 方法返回正负零值,然后根据大小进行逻辑排序。
(1)、古老的实现类Hashtable与其子类Properties
前面都说有古老的、线程安全的实现类,Map当然也不会少,它有一个与HashMap集合几乎相同,有不同的是它不允许使用null作为键和值,而它就是Hashtable类,由于它存取速度慢,目前基本被HashMap取代,所以我们了解一下有这个东西便好,但其中Hashtable类有一个子类Properties在实际开发中很常用,所以现在我们来理解一下这个Properties集合。
现在我们先了解其作用:Properties集合是用于处理属性文件,因为属性文件里的键和值都是字符串,所以Properties类里的键和值也字符串类型。
Properties类的方法有很多,我们了解它最常用的便好。
String getProperty(String key) 功能:可以根据属性文件(配置文件)中属性的键,获取对应属性的值。
看看例题代码吧:
import java.io.FileOutputStream;
import java.util.Properties;
public class TestProperties{
public static void main(String[] args) throws Exception {
Properties pro = new Properties(); //创建Properties对象
pro.setProperty("username", "mouse"); //向Properties中添加属性
pro.setProperty("password", "2020");
pro.store(new FileOutputStream("test.ini"),"title"); //将Properties中的属性保存到test.ini中
}
}
程序运行后,会在当前文件夹目录中生成一个test.ini文件,内容如下:
#title
#Mon Dec 30 11:19:14 CST 2019
password=2020
username=mouse
在实际开发中通常用这种方式处理属性文件。
虽然说是这么说,不知道你们有没有和我一样的疑问?Properties类可以处理属性文件,那然后呢?我拿这个属性文件能干什么?
据目前了解,它可以与数据库相关联、框架也有时需要,并且在日后一个项目放到生产环境,在开发维护过程中,如果有些地方需要修改,维护人员更改配置文件重启就OK了;不然在代码中进行修改,会累成狗的。
好,终于集合类的两个重要接口Collection和Map的介绍告一段落了。 到这里当然要有个小问题供大家思考了┗( ▔, ▔ )┛
Collection接口和Map接口的主要区别是什么? Collection和Map接口之间的主要区别在于:Collection中存储了一组对象,而Map存储关键字/值对。
可以看看这个博主的记录,里面包含了Collection接口、Map接口的总结和区别。转载: 我用CSDN这个app发现了有技术含量的博客,小伙伴们求同去《Collection和map的区别》,, 一起来围观吧 ! ! !
四、泛型
使用泛型的好处:它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。程序的可读性和健壮性更高。
泛型: 这位博主的泛型讲解的非常好,转载: 我用CSDN这个app发现了有技术含量的博客,小伙伴们求同去《小白都能看得懂的java泛型》,一起来围观吧!!!
五、两个工具类
接下来的内容,在我看来会模仿会用就行,所以就看看吧!
给大家介绍一下集合的两个工具类:Collection和Arrays. 了解会用就可以了。
1、Collections工具类
Collections工具类:适用于List集合的排序静态方法
static void reverse(List list) 将list集合元素顺序反转
static void shuffle(List list) 将list集合随机排序
static void sort(List list) 将list集合根据元素自然顺序排序
static void swap(List list, int i, int j) 将list集合中的i处元素与j处元素交换
下面代码演示这些方法:
import java.util.*;
public class TestCollections{
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list); //打印集合
Collections.reverse(list); //反转集合
System.out.println(list);
Collections.shuffle(list); //随机排序
System.out.println(list);
Collections.sort(list); //按自然顺序排序
System.out.println(list);
Collections.swap(list, 1, 3); //将索引为1的元素和索引为3的元素交换位置,索引也是从0开始的
System.out.println(list);
}
}
结果为:
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
[4, 1, 5, 2, 3]
[1, 2, 3, 4, 5]
[1, 4, 3, 2, 5]
工具嘛,知道怎么拿来用就行。Collections工具类除了对List集合的排序外,还可以对集合进行查找和替换,其方法为:
static int binarySearch(List list, Object o) 使用二分法搜索o元素在list集合中的索引,查找的list集合中元素必须是有序的
static Object max(Collection coll) 根据元素自然顺序,返回coll集合中最大的元素
static Object min(Collection coll) 根据元素自然顺序,返回coll集合中最小的元素
static boolean replaceAll(List list, Object o1, Object o2) 用o2元素替换list集合中所有的o1元素
int frequency(Collection coll, Object o) 返回coll集合中,o元素出现的次数
方法的使用:
import java.util.*;
public class TestCollections{
public static void main(String[] args) {
List list = new ArrayList(5);
list.add(11);
list.add(22);
list.add(33);
list.add(44);
list.add(55);
System.out.println(Collections.binarySearch(list, 33)); //打印元素33在list集合中的索引
System.out.println("集合中的最大元素:" + Collections.max(list));
System.out.println("集合中的最小元素:" + Collections.min(list));
Collections.replaceAll(list, 33, 11); //在集合中list中,用元素11替代元素33
System.out.println(Collections.frequency(list, 11)); //打印集合中元素11出现的次数,在查找最大最小时,11查了两次
}
}
结果为:
2
集合中的最大元素:55
集合中的最小元素:11
2
Collections还提供了对集合设置不可变、对集合对象实现同步控制等方法,有兴趣可以通过Java基础类库查找。
这些工具类会使用就好,继续来讲Array工具类。
2、Array工具类
Array是数组工具类,具体方法为:
static void sort(Object[] arr) 将arr数组元素按自然顺序排序
static int binarySearch(Object[] arr,Object o) 用二分搜索法搜索元素o在arr数组中索引
static fill(Object[] arr,Object o) 将arr数组中所有元素替换为o元素
static String toString(Object[] arr) 将arr数组转换为字符串
static object[] copyOfRange(Object[] arr,int i,int j) 将arr数组索引从i到j-1的j-i个元素复杂到一个新数组,不足的元素默认为0
方法演示:
import java.util.*;
public class TestArrays{
public static void main(String[] args) {
int arr[] = new int[] {3, 5, 2, 4, 1}; //创建数组初始化内容
System.out.println(Arrays.binarySearch(arr, 2)); //打印元素2在数组arr中的索引
Arrays.sort(arr); //对arr数组按自然顺序排列
for(int a : arr) {
System.out.print(a);
}
System.out.println();
System.out.println(Arrays.toString(arr)); //将数组转换为字符串并打印
int arr2[] = Arrays.copyOfRange(arr, 2, 9); //将arr[2]之后的元素复制到数组arr2中并打印,不足的元素默认为0
for(int a : arr2) {
System.out.print(a);
}
}
}
结果为:
2
12345
[1, 2, 3, 4, 5]
3450000
Arrays工具类一样还有很多方法,有兴趣的可以查阅Java基础类库。
3、集合转换
最后我们了解一下集合转换: 首先是集合转换为数组,代码演示:
import java.util.*;
public class TestCollectionToArray{
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(3);
list.add(2);
Object[] array = list.toArray(); //将集合转换为数组
for(Object object : array) {
System.out.print(object + "\t");
}
}
}
结果为:
1 3 2
其次是数组转换为集合,代码演示:
import java.util.*;
public class TestArrayToList{
public static void main(String[] args) {
String arr[] = new String[] {"1","3","2"};
List list = Arrays.asList(arr); //将数组转换为集合
System.out.println(list);
}
}
结果为:
[1, 3, 2]
需要注意的是,如果数组是int[]类型,应该先把int[]转换为Integer[],因为asList(Object[] arr)方法的参数必须是对象。
问:Collection接口与Collections工具类有什么区别? Collection是集合类的上级接口,继承于他的接口主要有Set和List,Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
通过上面的学习,相信已经能够掌握Java集合框架的相关知识,我也相信这篇文章有一定的瑕疵,毕竟是一个Java小白学习完集合类后所记录的笔记,希望大家发现问题后能提出来,Thanks♪(・ω・)ノ。 我的java集合类的笔记就到这里,O(∩_∩)O哈哈~