集合示例:

①、Iterator:迭代器,它是Java集合的顶层接口(不包括 map 系列的集合,Map接口 是 map 系列集合的顶层接口)

  Object next():返回迭代器刚越过的元素的引用,返回值是 Object,需要强制转换成自己需要的类型

  boolean hasNext():判断容器内是否还有可供访问的元素

  void remove():删除迭代器刚越过的元素

所以除了 map 系列的集合,我们都能通过迭代器来对集合中的元素进行遍历。

注意:我们可以在源码中追溯到集合的顶层接口,比如 Collection 接口,可以看到它继承的是类 Iterable

那这就得说明一下 Iterator 和 Iterable 的区别:

Iterable :存在于 java.lang 包中。

我们可以看到,里面封装了 Iterator 接口。所以只要实现了只要实现了Iterable接口的类,就可以使用Iterator迭代器了。

Iterator :存在于 java.util 包中。核心的方法next(),hasnext(),remove()。

这里我们引用一个Iterator 的实现类 ArrayList 来看一下迭代器的使用:暂时先不管 List 集合是什么,只需要看看迭代器的用法就行了

1         //产生一个 List 集合,典型实现为 ArrayList。

2         List list = new ArrayList();

3         //添加三个元素

4         list.add("Tom");

5         list.add("Bob");

6         list.add("Marry");

7         //构造 List 的迭代器

8         Iterator it = list.iterator();

9         //通过迭代器遍历元素

10         while(it.hasNext()){

11             Object obj = it.next();

12             System.out.println(obj);

13         }

②、Collection:List 接口和 Set 接口的父接口

  看一下 Collection 集合的使用例子:

1         //我们这里将 ArrayList集合作为 Collection 的实现类

2         Collection collection = new ArrayList();

3

4         //添加元素

5         collection.add("Tom");

6         collection.add("Bob");

7

8         //删除指定元素

9         collection.remove("Tom");

10

11         //删除所有元素

12         Collection c = new ArrayList();

13         c.add("Bob");

14         collection.removeAll(c);

15

16         //检测是否存在某个元素

17         collection.contains("Tom");

18

19         //判断是否为空

20         collection.isEmpty();

21

22         //利用增强for循环遍历集合

23         for(Object obj : collection){

24             System.out.println(obj);

25         }

26         //利用迭代器 Iterator

27         Iterator iterator = collection.iterator();

28         while(iterator.hasNext()){

29             Object obj = iterator.next();

30             System.out.println(obj);

31         }

③、List :有序,可以重复的集合。

由于 List 接口是继承于 Collection 接口,所以基本的方法如上所示。

1、List 接口的三个典型实现:

  ①、List list1 = new ArrayList();

    底层数据结构是数组,查询快,增删慢;线程不安全,效率高

  ②、List list2 = new Vector();

    底层数据结构是数组,查询快,增删慢;线程安全,效率低,几乎已经淘汰了这个集合

   ③、List list3 = new LinkedList();

    底层数据结构是链表,查询慢,增删快;线程不安全,效率高

怎么记呢?我们可以想象:

  数组就像身上编了号站成一排的人,要找第10个人很容易,根据人身上的编号很快就能找到。但插入、删除慢,要望某个位置插入或删除一个人时,后面的人身上的编号都要变。当然,加入或删除的人始终末尾的也快。

  链表就像手牵着手站成一圈的人,要找第10个人不容易,必须从第一个人一个个数过去。但插入、删除快。插入时只要解开两个人的手,并重新牵上新加进来的人的手就可以。删除一样的道理。

2、除此之外,List 接口遍历还可以使用普通 for 循环进行遍历,指定位置添加元素,替换元素等等。

1      //产生一个 List 集合,典型实现为 ArrayList

2         List list = new ArrayList();

3         //添加三个元素

4         list.add("Tom");

5         list.add("Bob");

6         list.add("Marry");

7         //构造 List 的迭代器

8         Iterator it = list.iterator();

9         //通过迭代器遍历元素

10         while(it.hasNext()){

11             Object obj = it.next();

12             //System.out.println(obj);

13         }

14

15         //在指定地方添加元素

16         list.add(2, 0);

17

18         //在指定地方替换元素

19         list.set(2, 1);

20

21         //获得指定对象的索引

22         int i=list.indexOf(1);

23         System.out.println("索引为:"+i);

24

25         //遍历:普通for循环

26         for(int j=0;j<list.size();j++){

27              System.out.println(list.get(j));

28         }

④、Set:典型实现 HashSet()是一个无序,不可重复的集合

1、Set hashSet = new HashSet();

  ①、HashSet:不能保证元素的顺序;不可重复;不是线程安全的;集合元素可以为 NULL;

  ②、其底层其实是一个数组,存在的意义是加快查询速度。我们知道在一般的数组中,元素在数组中的索引位置是随机的,元素的取值和元素的位置之间不存在确定的关系,因此,在数组中查找特定的值时,需要把查找值和一系列的元素进行比较,此时的查询效率依赖于查找过程中比较的次数。而 HashSet 集合底层数组的索引和值有一个确定的关系:index=hash(value),那么只需要调用这个公式,就能快速的找到元素或者索引。

  ③、对于 HashSet: 如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

    1、当向HashSet集合中存入一个元素时,HashSet会先调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置

      1.1、如果 hashCode 值不同,直接把该元素存储到 hashCode() 指定的位置

      1.2、如果 hashCode 值相同,那么会继续判断该元素和集合对象的 equals() 作比较

          1.2.1、hashCode 相同,equals 为 true,则视为同一个对象,不保存在 hashSet()中

          1.2.2、hashCode 相同,equals 为 false,则存储在之前对象同槽位的链表上,这非常麻烦,我们应该约束这种情况,即保证:如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

注意:每一个存储到 哈希 表中的对象,都得提供 hashCode() 和 equals() 方法的实现,用来判断是否是同一个对象

   对于 HashSet 集合,我们要保证如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。

LinkedHashSet的特征

LinkedHashSet是HashSet的一个子类,LinkedHashSet也根据HashCode的值来决定元素的存储位置,但同时它还用一个链表来维护元素的插入顺序,插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。查看LinkedHashSet的源码发现它是样的

public class LinkedHashSet<E>

extends HashSet<E>

implements Set<E>, Cloneable, java.io.Serializable {

private static final long serialVersionUID = -2851667679971038690L;

public LinkedHashSet(int initialCapacity, float loadFactor) {

super(initialCapacity, loadFactor, true);

}

....

在JAVA8中, LinkedHashSet没有定义任何方法,只有四个构造函数,它的构造函数调用了父类(HashSet)的带三个参数的构造方法,父类的构造函数如下

/**

* Constructs a new, empty linked hash set.  (This package private

* constructor is only used by LinkedHashSet.) The backing

* HashMap instance is a LinkedHashMap with the specified initial

* capacity and the specified load factor.

*

* @param      initialCapacity   the initial capacity of the hash map

* @param      loadFactor        the load factor of the hash map

* @param      dummy             ignored (distinguishes this

*             constructor from other int, float constructor.)

* @throws     IllegalArgumentException if the initial capacity is less

*             than zero, or if the load factor is nonpositive

*/

HashSet(int initialCapacity, float loadFactor, boolean dummy) {

map = new LinkedHashMap<>(initialCapacity, loadFactor);

}

由此可知,LinkedHashSet本质上也是从LinkedHashMap而来,LinkedHashSet的所有方法都继承自HashSet, 而它能维持元素的插入顺序的性质则继承自LinkedHashMap.

下面是一个LinkedHashSet维持元素插入顺序的例子

import java.util.LinkedHashSet;

import java.util.Set;

/**

* ClassName:  LinkedHashSets

* Description:

* date: 2019-11-20 17:18

*

* @author chengluchao

* @since JDK 1.8

*/

public class LinkedHashSets {

public static void main(String[] args) {

Set set = new LinkedHashSet();

set.add("abc");

set.add("efg");

set.add("hjk");

System.out.println(set);

set.remove(new String("abc"));

set.add("abc");

System.out.println(set);

}

}

输入如下

[abc, efg, hjk]

[efg, hjk, abc]

TreeSet类的特征

TreeSet实现了SortedSet接口,顾名思义这是一种排序的Set集合,查看jdk源码发现底层是用TreeMap实现的,本质上是一个红黑树原理。 正因为它是排序了的,所以相对HashSet来说,TreeSet提供了一些额外的按排序位置访问元素的方法,例如first(), last(), lower(), higher(), subSet(), headSet(), tailSet().
TreeSet的排序分两种类型,一种是自然排序,另一种是定制排序。

自然排序(在元素中写排序规则)

TreeSet 会调用compareTo方法比较元素大小,然后按升序排序。所以自然排序中的元素对象,都必须实现了Comparable接口,否则会抛出异常。对于TreeSet判断元素是否重复的标准,也是调用元素从Comparable接口继承而来额compareTo方法,如果返回0则是重复元素(两个元素I相等)。Java的常见类都已经实现了Comparable接口,下面举例说明没有实现Comparable存入TreeSet时引发异常的情况。

import java.util.Set;

import java.util.TreeSet;

/**

* ClassName:  TestSets

* Description: Tree自然排序

* date: 2019-11-20 17:27

*

* @author chengluchao

* @since JDK 1.8

*/

public class TestSets {

public static void main(String[] args) {

Set set = new TreeSet();

set.add(new Err());

set.add(new Err());

set.add(new Err());

System.out.println(set);

}

}

class Err {

}

运行程序会抛出如下异常

Exception in thread "main" java.lang.ClassCastException: clc.Err cannot be cast to java.lang.Comparable

at java.util.TreeMap.compare(TreeMap.java:1294)

at java.util.TreeMap.put(TreeMap.java:538)

at java.util.TreeSet.add(TreeSet.java:255)

at clc.TestSets.main(TestSets.java:17)

将上面的Err类实现Comparable接口之后程序就能正常运行了

class Err implements Comparable{

@Override

public int compareTo(Object o) {

return 0;

}

}

还有个重要问题是,因为TreeSet会调用元素的compareTo方法,这就要求所有元素的类型都相同,否则也会发生异常。也就是说,TreeSet只允许存入同一类的元素。例如下面这个例子就会抛出类型转换异常

public static void main(String[] args) {

Set set = new TreeSet();

set.add(1);

set.add("2");

System.out.println(set);

}

运行结果

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Date

at java.util.Date.compareTo(Date.java:131)

at java.util.TreeMap.put(TreeMap.java:568)

at java.util.TreeSet.add(TreeSet.java:255)

at clc.TestSets.main(TestSets.java:19)

定制排序(在集合中写排序规则)

TreeSet还有一种排序就是定制排序,定制排序时候,需要关联一个Comparator对象,由Comparator提供排序逻辑。下面就是一个使用Lambda表达式代替Comparator对象来提供定制排序的例子。下面是一个定制排序的列子

import java.util.Comparator;

import java.util.Set;

import java.util.TreeSet;

/**

* ClassName:  TestSets

* Description: Tree自然排序

* date: 2019-11-20 17:27

*

* @author chengluchao

* @since JDK 1.8

*/

public class TestSets {

public static void main(String[] args) {

Set set = new TreeSet(new MyCommpare());

set.add(new M(5));

set.add(new M(3));

set.add(new M(9));

System.out.println(set);

}

}

class M {

int age;

public M(int age) {

this.age = age;

}

}

class MyCommpare implements Comparator {

@Override

public int compare(Object o1, Object o2) {

M m1 = (M) o1;

M m2 = (M) o2;

return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;

}

}

当然将Comparator直接写入TreeSet初始化中也可以。如下。

import org.junit.Test;

import java.util.Comparator;

import java.util.Set;

import java.util.TreeSet;

/**

* ClassName:  TestSets

* Description: Tree自然排序

* date: 2019-11-20 17:27

*

* @author chengluchao

* @since JDK 1.8

*/

public class TestSets {

public static void main(String[] args) {

Set set = new TreeSet(new MyCommpare());

set.add(new M(5));

set.add(new M(3));

set.add(new M(9));

System.out.println(set);

}

/**

* Description: 将Comparator直接写入TreeSet初始化中1

*

* @method: testTreeSet

* @author: chengluchao

* @date: 2019-11-21 09:41

* @param:

* @return:

*/

@Test

public void testTreeSet() {

Set set = new TreeSet(new Comparator() {

@Override

public int compare(Object o1, Object o2) {

M m1 = (M) o1;

M m2 = (M) o2;

return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;

}

});

set.add(new M(5));

set.add(new M(3));

set.add(new M(9));

System.out.println(set);

}

/**

* Description: 将Comparator直接写入TreeSet初始化中

*

* @method: testTreeSetLam

* @author: chengluchao

* @date: 2019-11-21 09:41

* @param:

* @return:

*/

@Test

public void testTreeSetLam() {

Set set = new TreeSet((o1, o2) -> {

M m1 = (M) o1;

M m2 = (M) o2;

return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;

});

set.add(new M(5));

set.add(new M(3));

set.add(new M(9));

System.out.println(set);

}

}

class M {

int age;

public M(int age) {

this.age = age;

}

}

class MyCommpare implements Comparator {

@Override

public int compare(Object o1, Object o2) {

M m1 = (M) o1;

M m2 = (M) o2;

return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;

}

}

class Err implements Comparable {

@Override

public int compareTo(Object o) {

return 0;

}

集合————示例详解相关推荐

  1. redis储存实体类对象_Redis如何存储对象与集合示例详解

    前言 大家都知道在项目中,缓存以及mq消息队列可以说是不可或缺的2个重要技术.前者主要是为了减轻数据库压力,大幅度提升性能.后者主要是为了提高用户的体验度,我理解的是再后端做的一个ajax请求(异步) ...

  2. java网络编程阻塞_Java网络编程由浅入深三 一文了解非阻塞通信的图文代码示例详解...

    本文详细介绍组成非阻塞通信的几大类:Buffer.Channel.Selector.SelectionKey 非阻塞通信的流程ServerSocketChannel通过open方法获取ServerSo ...

  3. go语言字符串换行_Go语言中的字符串处理方法示例详解

    1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号(" ...

  4. 史上最易懂——ReactNative分组列表SectionList使用详情及示例详解

    React Native系列 <逻辑性最强的React Native环境搭建与调试> <ReactNative开发工具有这一篇足矣> <解决React Native un ...

  5. python中3or5什么意思_示例详解Python3 or Python2 两者之间的差异

    每门编程语言在发布更新之后,主要版本之间都会发生很大的变化. 在本文中,Vinodh Kumar 通过示例解释了 Python 2 和 Python 3 之间的一些重大差异,以帮助说明语言的变化. 本 ...

  6. php reactphp wss_workerman的基本用法(示例详解)

    workerman是什么? Workerman是一个异步事件驱动的PHP框架,具有高性能,可轻松构建快速,可扩展的网络应用程序.支持HTTP,Websocket,SSL和其他自定义协议.支持libev ...

  7. python的用途实例-python assert的用处示例详解

    使用assert断言是学习python一个非常好的习惯,python assert 断言句语格式及用法很简单.在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件 ...

  8. 线性代数带参数的线性方程组的求法示例详解

    线性方程组的求法与示例详解 线性方程组 由n个1维未知量,m个方程组成的组合叫做线性方程组. 特别的当方程组右边的值全都是0时叫做齐次线性方程组. 增广矩阵 在系数矩阵的右边添上一列,该列由线性方程组 ...

  9. python动态生成数据库表_Python-Flask:动态创建表的示例详解

    今天小编从项目的实际出发,由于项目某一个表的数据达到好几十万条,此时数据的增删查改会很慢:为了增加提高访问的速度,我们引入动态创建表. 代码如下: from app_factory import ap ...

最新文章

  1. 【ASP.NET开发】ASP.NET(MVC)三层架构知识的学习总结
  2. childNodes详解
  3. GET POST方法长度限制
  4. .NET的委托和匿名函数应用一例
  5. 【Kafka】kafka 监控指标项
  6. xml文件查看器_万能文件查看器,一个软件打开电脑所有文件
  7. lte网络测试用什么软件,LTE_测试软件使用教程.doc
  8. 宏碁Aspire 4560试用手记
  9. Android 百度语音合成手把手教学
  10. Vue3 组件通信方式【最好用的都在这里了】
  11. 手机PDF文件转换成图片教程来了,PDF转换器推荐
  12. 初学VUE 走马灯效果
  13. python 移动平均线_Python中的移动平均线
  14. 电信光猫路由模式转桥接
  15. java 使用相对路径读取文件
  16. 电脑磁盘更改盘符时出现参数错误该如何解决。
  17. 大数据专栏一-全自动化在线式当当销售情况分析预测系统
  18. VS 关于打开程序时不是有效的Win32应用程序
  19. php 熊掌号api,关于熊掌号资源提交功能API接口解读
  20. ​海外公链集体哑火? BATJ迅雷却成为区块链3.0拓荒者 【区块链3.0一周年】

热门文章

  1. 唱歌如何保持高位置_声乐唱歌唱到高音如何保持高位置?
  2. SATA、MSATA、M.2 SATA、M.2 NVME-实物接口
  3. 华科跟清华计算机专业,华科+清华 VS 南大+哥大 哪个更强
  4. Apollo 应用与源码分析:Monitor监控-硬件监控-GPS
  5. Python实现AO*算法进行与或图搜索
  6. python爬虫之requests库的用法(超全面的爬取网页案例)
  7. css设置textarea宽高,怎么用CSS让textarea宽度为100%? 自适应页面
  8. java如何让textarea填满面板_JavaFX TextArea:如何设置制表宽度
  9. 12.01-内存管理_定时器的循环引用
  10. 【Linux】X11VNC安装指导