说到Java集合,可以说是初学者必踩的坑了。

那么怎么才能学好Java集合呢?个人认为关键是要理清楚思路,从上而下,建立一套完整的思维体系,这样才能更好的去认识事物的本质。

先确立一下学习Java集合的目标:

1.会使用集合存储数据。

2.会遍历集合,把数据取出来。

3.掌握每种集合的特性。

总的集合框架如图所示:

 Collection<E>接口

首先从Collectiion 讲起 ,Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些操作方法可以用于操作多有的单列集合(所有子类都可以使用)。

方法如下(重点):

* public boolean add(E e): 把给定的对象添加到当前集合中。

* public boolean clear():清空集合中所有的元素。

* public boolean remove(E e):把给定的对象在当前集合中删除。

* public int size():输出集合中元素个数。

* public bollean contains(E e):判断当前集合是否包含指定对象。

* public boolean isEmpty():判断当前集合是否为空。

* public Object [ ] toArray:把集合中的元素储存在数组中

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class DemoCollection{
public static void main(String[] args){
//创建集合对象,使用多态。
Collection<String> coll = new ArrayList<>();//ArrayList是Collection的实现类
System.out.println(coll);
coll.add("寒冰射手");
coll.add("无双剑姬");
coll.add("满族之王");
System.out.println(coll); boolean b1= coll.remove("寒冰射手");//添加对象
System.out.println("b1是否移除:"+b1); boolean b2 = coll.contains("无双剑姬");//判断对象是否存在集合当中
System.out.println("b2是否包含:"+b2); int size = coll.size();//返回集合的大小
System.out.println("size:"+size); if(coll.isEmpty()){ //判断集合是否为空
System.out.println("集合为空");
}else{
Object[] arr = coll.toArray();//把集合中的元素存储在数组当中
for(int i = 0;i<arr.length;i++){
System.out.println("arr[i]");//输出数组中的元素
}
} //使用迭代器遍历集合
Iterator<String> it = coll.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
} //coll.clear();清空集合当中的元素
}
}

List 接口(java.util.List)

List接口继承自Collection接口,一般将List接口的对象称为List集合。List集合中重要是允许出现重复的元素,所有的元素以线性的方式存储。

List接口的特点:

1.有序的集合,存储元素和储存元素的顺序是一致的。

2.有索引,包含了一些带索引的方法(Collection抽取所有子接口的共性,所以不带索引)。

3.允许存储重复的元素。

List接口的常用方法(带索引 特有):

* public void add(int index,E element):将指定元素,添加在集合中的指定位置上。

* public E get (int index):返回集合中指定位置的元素。

* public E remove(int index):返回移除集合指定位置的元素。

* public E set(int index):返回替换集合中指定位置的元素。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class DemoSet {
public static void main(String[] args) {
List<String> list = new ArrayList<>();//创建List集合对象,使用多态
list.add("a");
list.add("b");
list.add("c");
list.add("d");
System.out.println(list); list.add(2,"f");//指定位置添加元素
System.out.println(list); list.remove(3);//移除指定位置元素
System.out.println(list); String str = list.get(1);//获取指定位置元素
System.out.println(str); list.set(0,"p");//替换指定位置元素
System.out.println(list); Iterator<String> it = list.iterator();//使用迭代器顺序取出元素,
while(it.hasNext()){
String str1 = it.next();
System.out.println(str1);
} }
}

ArrayList集合

ArrayList为List接口的实现类,底层储存为数组结构,用于元素的增删改查,属于最常用的集合(不同步)

常用方法:

* public boolea add(E e);

* public E get(int index);

* public E remove(int index);

* public int size();

import java.util.ArrayList;
import java.util.Iterator; public class DemoSet {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list); //注意,for循环遍历,长度用list.size
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(str);
} //迭代器遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str1 = it.next();
System.out.println(str1);
} }
}

LinkedList集合

LinkedList也为List接口的实现类,但其与ArrayList集合不同的是其底层数据存储的结构为链表结构(双向),包含大量操作首位元素的方法,查询慢,增删快。

常用方法(特有方法,不能使用多态):

* public void addFirst(E e):将指定元素插入此列表开头。

* public void addLast(E e):将指定元素插入此列表的末尾。

* public E getFirst():返回此列表的第一个元素。

* public E getLast():返回此列表的最后一个元素。

* public E removeFirst():移除并返回此列表第一个元素。

* public E removeLast():移除并返回此列表的最后一个元素。

* public E pop():从此列表所表示的堆栈处弹出一个元素。(等效与removeFirst()方法)

* public void push(E e):将元素推入此列表所表示的堆栈。(等效于add()方法)

* public boolean isEmpty():如果列表不包含元素,则返回true。

import java.util.Iterator;
import java.util.LinkedList; public class DemoSet {
public static void main(String[] args) {
show1();
} public static void show1(){
LinkedList<String> list = new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.push("f");
System.out.println(list); String f1 = list.getFirst();
System.out.println(f1); String l1 = list.getLast();
System.out.println(l1); String s1 = list.removeFirst();//等效pop()方法
System.out.println(s1); String s2 = list.removeLast();
System.out.println(s2); //list.clear(); 清空集中的元素,在获取集合中元素时会抛出NoSuchElementException //使用迭代器遍历Linked中的元素
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
} }
}

Vector集合

Vector也继承自List接口,底层也是一个实现可增长的对象数组,也可以通过索引来进行访问,但一般Vector使用较少,所以不在这进行详细讲解。

一般方法(特有):

* public void addElement(E e):添加元素到向量末尾。(等效于add()方法)

* public Enumeration<E> elements():返回该向量枚举。

Set接口

Set接口是Collection接口下第二大分支,也继承Collection接口。

Set接口特点:

1.不允许存储相同的元素

2.没有索引,没有带索引的方法,也不能使用普通的for循环。(一般来说,有索引就可以使用for循环来遍历)

Set方法不在详细描述,基本与Collection接口方法一致。

HashSet

HashSet是Set接口的实现类,由哈希表支持(HashMap实例),它不保证set的迭代顺序,即存储元素和取出元素的顺序有可能不一致。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; public class DemoSet {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
Iterator<Integer> it = set.iterator();
while(it.hasNext()){
int a = it.next();
System.out.println(a);
}
}
}

关于Set集合不允许重复元素的原理

Set集合在调用add方法时,add()方法会调用元素的hashCode方法和equals方法判断元素是否重复。

前提:存储的元素必须重写hashCode和equals方法。(如用HashSet存储自定义对象,必须重写equals和hashCode方法)

说一下hashCode()方法 :返回一个int型的哈希值(一串数字)。

import java.util.HashSet;

public class DemoSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
String s1 = new String("abc");
String s2 = new String("abc");
set.add(s1);
set.add(s2);
set.add("你好");
set.add("我好");
set.add("abc");
System.out.println(set);
}
}

set.add(s1): add方法会调用s1的hashCode方法,计算“abc”的哈希值,在集合中找有没有和“abc”哈希值一样的元素,发现没有就会把s1储存在集合当中。

set.add(s2):同上操作,发现有哈希冲突后,就会调用s2的equals方法去比较s2.equals(s1),equals返回true,认定两个元素相同,就不会把s2储存在集合当中。

set.add:("你好"):同s1操作相同。

set.add("我好"):哈希值与“你好”相同,但是equals方法返回false,认定“你好”,“我好”不同,就会把“我好”元素挂在“你好”下面,放入集合。

hashSet集合的 底层 哈希表结构 :数组+链表/红黑树。

数组 哈希值1 哈希值2
链表 元素1 元素3
链表 元素2 元素4

LinkedHashSet集合

特点:继承了HashSet集合,其底层是一个哈希表+链表,多了一条链表(记录元素的存储顺序),保证元素有序。

具体方方不再详述,与HashSet相同。

Collections集合工具类:

对集合进行操作,部分方法如下:

* public static <T> boolean addAll(Collection<T> c,T..elements):往集合中添加多个元素。

*
public static void shuffle(List<?> List):打乱集合中元素的顺序  。

* public static <T> void sort(List<T> list):将集合中元素按默认规则排序元素。(升序)

*注意:如果是自定义类型,使用sort()需要重写compaerTo()方法.

*
public static <T> void sort(List<T>,Comparator<?super
T>) :将集合中元素按指定规则排序。

例如:Collections.addAll(list,"a","b".....)(静态方法调用,直接类名.方法)。

Map<K,V>集合(有点懒,包括其子类就放一块讲完啦)

<key,value>双列集合,通多键值对方式组成。通过建可以找到其值。

Map集合的特点:

1.Map集合是一个双列集合,一个元素包含两个值(key,value)。

2.Map集合中的元素,key和value的数据类型可以相同,也可以不同。

3.Map集合中的元素,键是不允许重复的,但是值是可以重复的。

常用方法:

* public V put(K key,V value):把指定的键与值添加到Map集合当中。(存储键值对时,键相同,值不同,后添加的值会把原来的值覆盖)

* public V remove (Object key):把指定的键所对应的值对元素在Map集合中删除,返回被删除元素的值。

* public V get(Obejec key):获取键所对应的值

* boolean containsKey(Object key):判断集合中是否包含指定的键。

* public Set<K> keySet():获取Map集合中的所有键,并把它放入Set集合。(重要)

* public Set<Map.Entry<K,V>> entrySet():把键值对的对象(Entry)放入Set集合中。(重要)

import java.util.*;

public class DemoSet {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("a","a");
map.put("b","b");
map.put("c","c");
map.put("d","d");
map.put("a","f");
System.out.println(map); String str1 = map.get("a");
System.out.println(str1); String str2 = map.remove("c");
System.out.println(str2);
System.out.println(map); boolean flag = map.containsKey("c");
System.out.println("键C是否存在:"+flag); //遍历键值对,注意和之前的集合遍历不太一样
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
String value = map.get(key);
System.out.println(key+"="+value);
}
System.out.println("------------------------------------");//华丽的分割线 Map.Entry为其Map内置接口
//使用entrySet遍历
Set<Map.Entry<String, String>> entry = map.entrySet();
Iterator<Map.Entry<String, String>> iterator = entry.iterator();
while(iterator.hasNext()){
Map.Entry<String, String> next = iterator.next();
System.out.println(next);
}
System.out.println("------------------------------------");//华丽的分割线
//也可使用增强for循环遍历
for(Map.Entry<String, String> s1:map.entrySet()){
System.out.println(s1);
} }
}

*注意:Map.Entry<k,v>:在Map接口中由一个内部接口Entry,当Map集合一创建,就会创建一个Entry对象,用来记录键值对。

可以把Map.Entry<K,V>,理解成一种引用类型,在增强for循环中去遍历使用,用来接收传来的键值对。

HashMap集合

HashMap<k,v>集合为Map<k,v>接口的实现类,其底层为哈希表。为无顺序集合的集合,即存取顺序不一致,线程不安全,不同步,多线程。

Hashmap存储自定义类型键,自定义类型的键就要重写hashcode方法和equals方法,保证键的唯一性。值可以重复。(具体不详述)

LinkedHashMap集合

LinkedHashMap是HashMap的子类。其底层是哈希表+链表(保证迭代顺序),它是一个有序的集合,存取顺序一致。

Hashtable集合

Hashtable为Map接口的实现类,其底层也为哈希表,同步且为单线程集合,不常用。Hashtable 不能存取null值。

如果在Hashtable集合中存放null,则会抛出NullPointerException异常。

但是Hashtable的子类Properties集合依然活跃,Properties是唯一和IO流相结合的集合。

更新~~~

关于两道道Map集合的习题的思考

题目一:计算一个字符串每个字符出现的次数

分析:

1.使用Scanner获取用户输入的字符串。

2.创建Map集合,key是字符,value是出现的次数。

3.使用字符串的toCharArray方法去拆分字符串,返回一个char类型数组,使用for循环去遍历数组中的每个字符 。

4.判断字符是否存在Map集合当中:

如果存在,则用Map集合的get方法去获取value,value++,在重新把<Key,Value>放入集合中。

如果不存在,则放入字符。value为1.

5.遍历Map集合。

代码如下:

import java.util.*;

public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.next();
HashMap<Character,Integer> map =new HashMap<>();
char[] arr = str.toCharArray();
for (int i = 0; i <str.length() ; i++) {
if(map.containsKey(arr[i])){
Integer value = map.get(arr[i]);
value++;
map.put(arr[i],value);
}else{
map.put(arr[i],1);
}
}
Set<Map.Entry<Character, Integer>> entries = map.entrySet();
Iterator<Map.Entry<Character, Integer>> it = entries.iterator();
while(it.hasNext()){
Map.Entry<Character, Integer> next = it.next();
System.out.println(next);
}
}
}

题目二: 关于斗地主案例的集合习题,代码如下:

由于不是JDK9,所以没有用List.of(),所以使用Collections.addAll()方法去添加多个元素到集合。

涉及洗牌,排序,发牌,属于比较经典的综合的案例:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List; public class DouDiZhu {
public static void main(String[] args) {
HashMap<Integer, String> poker = new HashMap<>();
ArrayList<Integer> pokerIndex = new ArrayList<>();
List<String> colors = new ArrayList<>();
List<String> numbers = new ArrayList<>();
Collections.addAll(colors, "♠", "♥", "♣", "♦");
Collections.addAll(numbers, "2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");
int index = 0;
poker.put(index, "大王");
pokerIndex.add(index);
index++;
poker.put(index, "小王");
pokerIndex.add(index);
index++;
for (String color : colors) {
for (String number : numbers) {
poker.put(index, color + number);
pokerIndex.add(index);
index++;
}
}
//System.out.println(poker);
//System.out.println(pokerIndex);
Collections.shuffle(pokerIndex);//洗牌
ArrayList<Integer> player01 = new ArrayList<>();
ArrayList<Integer> player02 = new ArrayList<>();
ArrayList<Integer> player03 = new ArrayList<>();
ArrayList<Integer> dipai = new ArrayList<>();
for (int i = 0; i < pokerIndex.size(); i++) {
Integer in = pokerIndex.get(i);
if(i>=51){
dipai.add(in);
}else if(i % 3 == 0){
player01.add(in);
}else if(i % 3 == 1){
player02.add(in);
}else if(i % 3 == 2){
player03.add(in);
}
}
Collections.sort(player01);//sort默认升序排序
Collections.sort(player02);
Collections.sort(player03);
Collections.sort(dipai); lookPoker("玩家一号",poker,player01);
lookPoker("玩家二号",poker,player02);
lookPoker("玩家三号",poker,player03);
lookPoker("底牌",poker,dipai);
}
public static void lookPoker(String name,HashMap<Integer,String> poker,ArrayList<Integer> list){
System.out.print(name+": ");
for (Integer key : list) {
String value = poker.get(key);
System.out.print(value+" ");
}
System.out.println();
}
}

好了,集合就到这吧~

Java集合那点事, 满满干货~的更多相关文章

  1. Java集合框架知多少——干货!!!

    Java集合框架的组成 注意:四个接口的区别 ① Collection:存储无序的.不唯一的数据: ② List:存储有序的.不唯一的数据: ③ Set:存储无序的.唯一的数据: ④ Map:以键值对 ...

  2. java集合讲解干货集

    文章都来自网络,收集后便于查阅. 1.Java 集合系列01之 总体框架 2.Java 集合系列02之 Collection架构 3.Java 集合系列03之 ArrayList详细介绍(源码解析)和 ...

  3. 【新手向】如何学习Java集合

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 如果认识我的同学可能就知道,我已经写过很多系列级 ...

  4. Java集合详解2:一文读懂Queue和LinkedList

    <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...

  5. Java集合的10个最常见问题

    以下是一些在Stackoverflow上经常被问起的与Java集合相关的问题.在你查阅这些问题之前,最好先去看看[Simple Java]Java集合框架的接口和类层次关系结构图. 什么时候优先选择L ...

  6. 【JAVA集合框架之List】

    一.List接口概述. List有个很大的特点就是可以操作角标. 下面开始介绍List接口中相对于Collection接口比较特别的方法.在Collection接口中已经介绍的方法此处就不再赘述. 1 ...

  7. Java集合容器简介

    Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),Attr ...

  8. Java集合框架面试题

    www.cnblogs.com/zhxxcq/archive/2012/03/11/2389611.html 这里的两个图很形象,由于放进图片链接,图片显示不了,所以只能给出该链接. Java集合框架 ...

  9. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

随机推荐

  1. 聊一聊 InnoDB 引擎中的索引类型

    索引对数据库有多重要,我想大家都已经知道了吧,关于索引可能大家会对它多少有一些误解,首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书 ...

  2. 把 CPU “玩”起来

    前言 从开始学习编程之后,就渐渐痴迷于技术,平时遇到购书满减活动时就忍不住买一堆书.前两天闲着无聊,翻开了去年买的<编程之美>,目录里的“让 CPU 占用率听你指挥”吸引力我的眼球.这一年 ...

  3. javaweb-codereview 学习记录-1

    Servlet是在Java Web容器上运行的小程序,通常我们用Servlet来处理一些较为复杂的服务器端的业务逻辑.值得注意的是在Servlet3.0之后(Tomcat7+)可以使用注解方式配置Se ...

  4. 人生中的第一篇OI博客及博客规划

    这是笔者第一次在博客园里发表文章,也同样是第一次来写关于OI的一些想法,此篇的主题是想总体对日后的博客有具体的规划. 首先,笔者创办博客并发表观点于看法的目的是记录自己对于题目或竞赛的观念,主要以题解 ...

  5. Oracle 11g 安装过程及测试方法

    大家可以根据自己的操作系统是多少位(32位或64位)的,到官网下载相应的安装程序,如下图所示. 有一点需要注意,Oracle的安装程序分成2个文件,下载后将2个文件解压到同一目录即可.     下载完 ...

  6. JS DOM中Ajax的使用

    一.概念 全称:Asynchronors Javascript XML  异步JS数据交换格式. [Asynchronous]:异步的,即在执⾏ AJAX 请求时不会阻塞后⾯代码的运⾏.[JavaSc ...

  7. JVM第一弹

    JVM第一弹 基本概念 JVM是可运行java代码的假想计算机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收.堆和一个存储方法域.JVM是运行在操作系统之上的,它与硬件没有直接的交互. 运行 ...

  8. volatile梳理

    volatile 可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值. 在Java中为了加快程序的运行 ...

  9. 实验18:HDLC和PPP

    实验15-1:HDLC 和PPP 封装 Ø     实验目的通过本实验,读者可以掌握如下技能:(1) 串行链路上的封装概念(2) HDLC 封装(3) PPP 封装 Ø     实验拓扑 实验步骤n  ...

  10. linux入门系列10--firewalld防火墙管理

    上一篇文章学习了用户及文件相关权限,本篇继续学习防火墙技术. 防火墙作为公网与内网之间的保护屏障,对系统至关重要.防火墙又分为硬件防火墙和软件防火墙,主要功能都是依据设置的策略对穿越防火墙的流量进行过 ...