说到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();
}
}

好了,集合就到这吧~

最新文章

  1. Spill data to tempdb
  2. 【原创】如何用Android Studio断点安卓自带Service或Bind类型的Service
  3. (Hibernate进阶)Hibernate映射——一对多关联映射(七)
  4. CentOS禁用root本地或远程ssh登录
  5. (转载) 数组a[]={3,5,2,4,1,8},要求从a中找出所有“和”等于10的子集
  6. 论山寨手机与Android联姻 【8】 自己动手做XP手机
  7. 道路软件质量:SourceMonitor
  8. svn密码问题
  9. ggplot2 scale相关设置
  10. android 没有main函数,怎么找到程序执行入口呢?以及activity主要生命周期的方法说明
  11. 开源OSS.Social微信项目进阶介绍
  12. HTML5之placeholder属性以及如何更改placeholder属性中文字颜色
  13. Media Player Classic - HC 源代码分析 6:MediaInfo选项卡 (CPPageFileMediaInfo)
  14. 多设备同时进行monkey抗压测试
  15. ThreadLocal和线程同步机制对比
  16. Apache log4net&trade; 手册&mdash;&mdash;介绍【翻译】
  17. Win32汇编学习(4):绘制文本
  18. solr 请求参数过长报错,Solr配置maxBooleanClauses属性不生效原因分析
  19. linux修改hosts
  20. Vue(SPA) WebPack模块化打包、SEO优化(Vue SSR服务端同构直出)、全浏览器兼容完整解决方案

热门文章

  1. Djaingo 日志配置
  2. Linux下利用Ant调用Jmeter脚本生成HTML测试报告
  3. Oracle GoldenGate for DB2
  4. [bzoj3926] [loj2137] [Zjoi2015] 诸神眷顾的幻想乡
  5. hbase伪分布式安装以及实例演示
  6. 《编写高质量代码:改善C#程序的157个建议》是C#程序员进阶修炼的必读之作
  7. js解析json时报:Unexpected token s in JSON at position 0
  8. WPF另类实现摄像头录像
  9. Django面试集锦(1-50)
  10. c++中值传递,址传递,引用传递