Java集合

一、hashCode与equals

这两个方法来自于Object类,所以每个类型都会自动继承这2个方法.这2个方法本质上并没有任何关系,彼此独立,而且这两个方法在脱离集合的环境下也是可以使用的.但这两个方法的理解对于更好的使用集合是必不可少的.

1.equals

Object类对equals的默认实现如下

public boolean equals(Object obj) {
   return (this == obj);
}

这种实现只是表示引用相等,字符串对这个方法进行了重写,用于判断两个字符串的值是否相等.比如下面的代码

String s = new String("abc");
String s2 = new String("abc");
System.out.println(s==s2); //false
System.out.println(s.equals(s2));//true

通常重写 equals() 方法时,要重写 hashCode() 方法,以表示:如果两个对象是 equals 的,那么其 hashCode() 值也应该一样。

2.hashCode

hashCode方法主要用来支持java 集合框架中的Hash相关的集合,比如HashMap,HashSet等.

在Object类中hashCode的实现如下:

public native int hashCode();

这个是一个本地方法,其默认实现返回的hashCode是对象的内存地址进行hash算法得出的值.在hashCode的注释中,对hashCode的实现要求如下:

  • 任何时候,反复调用同一个对象的hashCode方法,返回的值要一样

  • 如果两个对象equals相等,那么其hashCode应该要一样

  • 如果两个对象非equals相等,其hashCode可以一样,但不强制要求.

 

Hash 算法又叫散列算法,由 Hash(人名)首先提出。

Hash 算法:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。

为什么要用 hash 算法?

Hash 算法的输出值是固定长度的,该值可以被用来作为内存地址。 这样取的时候,就可以通过计算其 hash 值来获取所在内存存储单元的地址,而快速的读取其存储的内容。

 

二、Comparable 与Comparator

jdk中的Comparable接口与Comparator接口都与排序有关,当对象放入到一些有序的集合时会对对象的排序性有要求,所以有必要了解这2个接口

1.Comparable

若一个类实现了Comparable接口,就意味着“该类支持排序” 此接口是jdk 1.2推出的,它的代码如下:

//java.lang jdk 1.2就有
public interface Comparable<T> {
 public int compareTo(T o);
}

当一个类实现了此接口时,通常是此实现类与compareTo方法传递过来的参数进行比较,比较的规则是当自身小于传递过来的对象时返回负数,相等就返回0,大于就返回正数.比如下面的代码:

class Student implements Comparable<Student>{   
 String name;  
 int age;  
 
 Student(String name,int age){  
   this.name=name;  
   this.age=age;  
}  
 public int compareTo(Student st){  
   if(age==st.age)  
  return 0;  
   else if(age>st.age)  
  return 1;  
   else  
  return -1;  
}  
}  

实现了Comparable接口后,此对象放入到集合中就可以对集合中的元素进行排序了,比如下面的代码

ArrayList<Student> al=new ArrayList<Student>();  
al.add(new Student("a",23));  
al.add(new Student("b",27));  
al.add(new Student("c",21));  
 
Collections.sort(al);  
for(Student st:al){  
System.out.println(st.name+" "+st.age);  
}

输出结构为:

c 21
a 23
b 27

上面的结果可以看出以升序排序,如果想改为降序排序,必须修改Student类中的实现,把返回1的地方改为返回-1,返回-1的地方改为1.也就是说想改变排序规则必须修改源代码.还有一个不足之处就是只支持固定的排序规则,比如现在的实现只支持按年龄排序,不支持按名字排序.基于这种情况就需要使用Comparator来完成这样的功能.

2.Comparator

此接口在java.util包下,用来实现两个对象之间比较功能的.并且也并不要求被比较的对象实现某个接口.此接口的核心比较代码如下:

public interface Comparator<T> {
 int compare(T o1, T o2);
}

compare方法的比较逻辑与Comparable接口的compareTo方法类似,当第一个参数小于第二个参数时返回负数,相等返回0,大于返回正数.比如下面的代码实现了对Student类的年龄的比较

class AgeComparator implements Comparator<Student>{  
 public int compare(Student s1,Student s2){  
   if(s1.age==s2.age)  
  return 0;  
   else if(s1.age>s2.age)  
  return 1;  
   else  
  return -1;  
}  
}  

下面的代码实现了对名字的比较

class NameComparator implements Comparator<Student>{  
 public int compare(Student s1,Student s2){
   //String类本身实现了Comparable接口
   return s1.name.compareTo(s2.name);  
}  
}  

使用方式如下:

ArrayList<Student> al=new ArrayList<Student>();  
al.add(new Student("a",23));  
al.add(new Student("b",27));  
al.add(new Student("c",21));  

System.out.println("依据名字进行比较");
Collections.sort(al,new NameComparator());  
for(Student st:al){  
System.out.println(st.name+" "+st.age);  
}

System.out.println("依据年龄进行比较");
Collections.sort(al,new AgeComparator());  
for(Student st:al){  
System.out.println(st.name+" "+st.age);  
}

最终输出的结果为

依据名字进行比较
a 23
b 27
c 21

依据年龄进行比较
c 21
a 23
b 27


三、简介

数组主要存放的是同类型的数据,其最大的一个缺点就是其大小不能动态调整,这对于一些预先不确定数据量大小的情况无法应付,所以java推出了集合框架.

 

四、集合框架图

集合框架是存储于操纵一组对象的统一架构,它由一系列的接口和实现类组成,这些类型包含了如何存储对象以及操作这些数据的算法,比如排序算法.

整个java集合框架由Collection接口与Map接口代表.当然有一种说法认为java的集合框架只包含Collection接口体系,不包含Map接口代表的体系.下面是包含Collection与Map的整个架构:

下图是Collection接口代表的核心体系架构

image-20190718192054677

五、List

List接口代表线性结构的集合,它以线性的方式来存储数据,并且允许存储重复的数据.此接口的主要实现类如下:

  •  ArrayList

  •  LinkedList

  •  Vector

  •  Stack

1.ArrayList

ArrayList是一个内部用数组实现List接口的集合类.

ArrayList<String> list=new ArrayList<String>();
list.add("a");
list.add("b");  

在实例化集合对象时最好指定初始容量,容量大小尽量与预计存放的数据量差不多,值建议用2的n次方.这样可以减少集合频繁扩容造成的性能损失.如果不指定容量大小,ArrayList默认的大小为10.

ArrayList<String> list=new ArrayList<String>(4);

ArrayList由于内部是数组实现的集合,它支持通过索引来取得集合中的数据,比如

list.get(0)

通过索引取值的方式,其时间复杂度是个常量值.性能很高.但ArrayList集合删除数据或者往中间插入数据性能不高,因为其要逻动数据.

在遍历集合时,尽量不要进行集合的修改操作,比如删除元素.这非常容易产生bug,比如下面的代码:

List<String> list = new ArrayList<>();
list.add("1");
list.add("2");

for (String item : list) {
 if ("2".equals(item)) { //把这里的2改为1试试
   list.remove(item);
}
}

for (String item : list) {
 System.out.println(item);
}

 

2.LinkedList

LinkedList用双链表来实现List接口,因而此类型往里面插入,删除速度性能较高.但通过索引取值的时间复杂度是O(n),性能不高.基本使用方法如下:

LinkedList<String> al=new LinkedList<String>();  
al.add("a");  
al.add("b");  

 

六、Iterable与Iterator

实现了此接口的类型支持foreach循环,由于Collection接口的父类型就是Iterable,所以所有的Collection都支持foreach循环.

此接口的主要方法为Iterator<T> iterator()此Iterator就是真正完成迭代功能的接口.Iterator接口的主要成员如下:

  • hasNext():检查迭代器是否还有元素

  • next():获取迭代器的下一个元素.

  • remove:删除一个元素.

迭代器(Iterator)中完成foreach循环的方法只有hasNext与next,remove主要用来完成在迭代的时候删除元素.

ArrayList<String> list=new ArrayList<String>();
list.add("a");
list.add("b");

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

在迭代集合的时候,如果要删除元素建议用迭代器实现.

 

七、Map

Map类型是一种键值对类型,键和值是一一映射(map)的,每一个键值对称之为一个条目(Entry).Map包含唯一的键.Map集合非常适合依据键来搜索,更新,删除元素的情况.map的体系结构如下:

image-20190718210958036

从上图中看出Map的类型主要有以下几个:

  • HashMap:它不维护插入元素的顺序(order)

  • LinkedHashMap:它维护插入的顺序

  • TreeMap:它支持排序.默认是升序排列Map中的元素.

Map不允许有重复的键,但值允许重复.HashMap与LinkedHashMap允许键与值存放null值,但TreeMap的键与值都不允许null值.

1.HashMap

HashMap 首先初始化一块内存(数组)。把内存划分为一个一个的存储空间(bucket),每一个存储空间都有一个地址与其对应。但是,一个存储空间,不限于只存一对键值对(HashMap 使用 LinkedList 存储多个具有相同 hashCode 的键值对。新加的放在最前).基本使用如下:

Map<Integer,String> map=new HashMap<Integer,String>();    
map.put(1,"a");  
map.put(5,"b");
map.put(2,"b");
map.get(1) //去值,结果为:a

 

2.存值

存放值的时候会依据键的hasCode值来确定存放的槽位(backet),如果此槽位没内容,直接存放.如果此槽位有内容就比较槽位已有对象与即将插入对象的相等性(equals方式比较),相等的话就覆盖,不相等就直接插入此槽位的linkedList里面去.

3.取值

使用一个object作为键来取HashMap 中对应的值时,HashMap 的工作方法是:通过传入的键的 hashcode() 在Map中找槽位,当找到这个槽位后再通过 equals() 来比较传入的object和地址中的object(s)(可能是多个),结果为 true 就取出 value。

4.遍历

HashMap可以分别对其键,值,键值对进行遍历,效率最高的遍历方式是键值对的遍历方式.因为只遍历键来取值的话其实是把集合遍历了2次

//键的遍历
for(Integer k: map.keySet()) {
 System.out.println(k);
}
//值的遍历
for(String v:map.values()) {
 System.out.println(v);
}
// 键值对遍历
for(Map.Entry<Integer,String> entry: map.entrySet()) {
 System.out.println("key:" + entry.getKey() + " value: " + entry.getValue());
}

5.对象作为key

假设有这么一个类想作为Map集合中的键,在存放到集合中的时候需要注意处理其hashCode与equals方法的重写问题.

public class Person {
private int id;
public Person(int id) {
this.id = id;
}
}

使用的代码如下,最终集合中的数量为2.因为p1与p2是两个不同的对象.

Map<Person,String> map = new HashMap<>(4);
Person p1 = new Person(1);
Person p2 = new Person(1);
map.put(p1, "a");
map.put(p2,"b");
System.out.println(map.size());//输出的结果是2

如果你基于业务的需要觉得两个Person对象的id是一样的话,应该是相等的,那么你此时就应该重写equals方法.按照规范,重写equals方法时应该也相应的重写hashCode方法.利用eclipse帮我们生成的equals与hashCode方法实现,最终person类的代码如下:

public class Person {
private int id;
public Person(int id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
return true;
}
}

再次运行上面的代码会发现最终集合中的数量是1.

八、TreeMap

内部用树结构实现的一个有序的Map类型.其排序是依据键来进行排序的,并且要求所有的键实现了Comparable接口

Map<Integer,String> map=new TreeMap<Integer,String>();    
map.put(1,"a");  
map.put(5,"b");
map.put(2,"b");
for(Map.Entry<Integer,String> entry: map.entrySet()) {
 System.out.println("key:" + entry.getKey() + " value: " + entry.getValue());
}

输出的结果为:

key:1 value: a
key:2 value: b
key:5 value: b

如果存放的键的类型没有实现Comparable接口会报ClassCastException.键的类型必须实现了Comparable接口.代码如下:

public class Person implements Comparable<Integer> {
private int id;
public Person(int id) {
this.id = id;
}
 public int getId() {
return this.id;
}
// 省略hashCod与equals方法的实现,与上面的一样.
@Override
public int compareTo(Person p) {
if(this.id < p.getId()) {
return -1;
}else if(this.id == p.getId()) {
return 0;
}else {
return 1;
}
}
}

使用此类的代码如下,最终输出的结果为1,3,10的升序排列

Map<Person,String> map = new TreeMap<>();
Person p1 = new Person(10);
Person p2 = new Person(1);
Person p3 = new Person(3);
map.put(p1, "a");
map.put(p2,"b");
map.put(p3,"c");
for(Map.Entry<Person,String> entry:map.entrySet()) {
 System.out.println(entry.getKey().getId());
}

 

九、Set

它主要用来存放不重复的数据,可以存放null值,但只能存放一个null值.set集合是无序的,主要实现类有HashSet,LinkedHashSet,TreeSet.可以利用Set元素唯一的特性快速对一个集合进行去重的操作.

1.HashSet

内部用一个hash map集合来存放数据,存放数据时利用对象的hashcode来确定是否存在重复.基本使用如下:

HashSet<String> set=new HashSet<String>();  
set.add("a");  
set.add("b");
set.add("b");  // 总数量为2

2.TreeSet

此集合是有序的.基本使用方法如下:

HashSet<String> set=new TreeSet<String>();  
set.add("a");  
set.add("b");
set.add("c"); // 总数量为2

 

十、Stack

栈是一种先进后出的数据结构,java集合中用Stack类实现栈这种数据结构,此类是Vector的子类,并添加了push,pop,peek等栈专有的方法.其基本使用方法如下:

Stack<String> stack = new Stack<String>();  
stack.push("a");  
stack.push("b");  
stack.pop();

 

十一、Queue

队列是一种先进先出的数据结构,在集合框架中用Queue接口代表队列.常见的实现类有:

  •  LinkedList

  •  PriorityQueue

  •  ArrayDeque()

LinkedList

 

LinkedList<String> ll = new LinkedList<>();
ll.addFirst("a");
ll.addFirst("b");
String value = ll.removeLast();// value为a

 

十二、总结

 

image-20200506113802586

image-20200506113837667

image-20200506113918505

image-20200506141701857

十三、Collections

此类是java.util包下的一个工具类,不能实例化,此类包含的都是一些静态的方法,用来操作集合或者返回集合.此类包含的方法主要有以下一些作用

  •  排序

  •  搜索

  •  往集合填充,拷贝数据

  •  求取集合的最大值最小值

  •  获取集合的只读视图

  •  获取线程安全的同步集合

  •  获取空的集合

  •  获取检查集合

下面的代码演示了Collections类的一些常见用法

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(4);
list.add(3);
list.add(1);
list.add(2);
list.add(3);
// 排序
Collections.sort(list);
// 二分查找的前提是排序好的元素
System.out.println( Collections.binarySearch( list , 8 ) );  // 找不到返回-1
// 反序集合输出
Collections.reverse( list );
System.out.println( list );
// 求最大值
System.out.println( Collections.max( list ) );   // 4
//   使用指定的元素替换指定集合中的所有元素
Collections.fill( list, 5 );
System.out.println( list );

十四、Arrays

此类是java.util包下的一个工具类,不能实例化,主要包含一些操作数组或者返回数据的工具方法.此类的方法主要有如下功能

  • 排序

  • 二分搜索

  • 填充

  • 拷贝

  • 转换为流

  • 字符串显示数组

  • 转换为集合视图

下面的代码是一些常见的操作

// 将数组转换为集合视图
ArrayList<Integer> list = new ArrayList<Integer>();
Integer is[] = new  Integer[]{6,7,8};
List<Integer> list2 =  Arrays.asList(is);
list.addAll( list2 );
System.out.println( list );

// 将List转换为数组
Object [] ins =  list.toArray();
System.out.println( Arrays.toString( ins ) );

 

十五、有序性与稳定性

在阿里巴巴的编码规范中有这么一句话:合理利用集合的稳定性(order)和有序性(sort),避免集合的无序性和不稳定性带来的负面影响。稳定性指集合每次遍历的元素次序是一定的。有序性是指遍历的结果按某种比较规则依次排序的。

如ArrayList是order/unsort,HashMap是unorder/unsort,TreeSet是order/sort

比如下面的代码演示了HashMap的不稳定:

Map<Integer,Integer> map = new HashMap<>();
map.put(1,11);
map.put(2,22);
for(Map.Entry<Integer, Integer> entry:map.entrySet()) {
System.out.println(entry.getKey());
}
System.out.println("------");
map.put(17,17);
for(Map.Entry<Integer, Integer> entry:map.entrySet()) {
System.out.println(entry.getKey());
}

输出的结果是:由于新插入一个值导致两次遍历的结果是不一样的.这就是不稳定性

1
2
------
1
17
2

 

十六、null的处理

集合类KeyValue父类说明
Hashtable 不允许null 不允许null Dictionary 线程安全
ConcurrentHashMap 不允许null 不允许null AbstractMap 锁分段
TreeMap 不允许null 允许 AbstractMap 线程不安全
HashMap 允许 允许 AbstractMap 线程不安全

 

 

十七、异同点

 

1.ArrayList和LinkedList

(1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
(2)对于随机访问get和set,ArrayList绝对优于LinkedList,因为LinkedList要移动指针。 
(3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 
这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

2.HashTable与HashMap

相同点:

(1)都实现了Map、Cloneable、java.io.Serializable接口。
(2)都是存储"键值对(key-value)"的散列表,而且都是采用拉链法实现的。

不同点:

(1)历史原因:HashTable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 。
(2)同步性:HashTable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
(3)对null值的处理:HashMap的key、value都可为null,HashTable的key、value都不可为null 。
(4)基类不同:HashMap继承于AbstractMap,而Hashtable继承于Dictionary。

      Dictionary是一个抽象类,它直接继承于Object类,没有实现任何接口。Dictionary类是JDK 1.0的引入的。虽然Dictionary也支持“添加key-value键值对”、“获取value”、“获取大小”等基本操作,但它的API函数比Map少;而且Dictionary一般是通过Enumeration(枚举类)去遍历,Map则是通过Iterator(迭代M器)去遍历。 然而由于Hashtable也实现了Map接口,所以,它即支持Enumeration遍历,也支持Iterator遍历。
      AbstractMap是一个抽象类,它实现了Map接口的绝大部分API函数;为Map的具体实现类提供了极大的便利。它是JDK 1.2新增的类。
   
(5)支持的遍历种类不同:HashMap只支持Iterator(迭代器)遍历。而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。

 

3.HashMap、Hashtable、LinkedHashMap和TreeMap比较

     Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。

     Hashtable 与 HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

     LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。对于LinkedHashMap而言,它继承与HashMap、底层使用哈希表与双向链表来保存所有元素。其基本操作与父类HashMap相似,它通过重写父类相关的方法,来实现自己的链接列表特性。

     TreeMap实现SortMap接口,内部实现是红黑树。能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。 

 

使用场景


     一般情况下,我们用的最多的是HashMap,HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
     TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
     LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。

 

4.HashSet、LinkedHashSet、TreeSet比较

Set接口
Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

HashSet
HashSet有以下特点:
->  不能保证元素的排列顺序,顺序有可能发生变化。
->  不是同步的。
->  集合元素可以是null,但只能放入一个null。
    当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等。
    注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

LinkedHashSet
    LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
    LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

TreeSet类
    TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
    TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0。

 

5、Iterator和ListIterator区别

     我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器)。使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了。但是在使用的时候也是有不同的。List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:

(1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
(4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。

6、Collection 和 Collections区别

(1)java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

(2)java.util.Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。

 

posted @ 2020-12-16 09:25  Winton-H  阅读(246)  评论(0编辑  收藏  举报