Java集合
数组作为容器,可以存储基本数据类型,也可以存储引用数据类型,数组一旦定义出来,长度就固定了,而且也只能存储引用数据类型,用起来不太方便,所以就引出了集合的概念。
集合
集合的长度是可变的,集合中可以存储不同的数据类型,但是集合不能存储基本数据类型
集合中的方法
Collection: 包括 list 和 set
a/添加功能 boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
[Java] 纯文本查看 复制代码 Collection con = new ArrayList();
con.add(s1);
con.add(s2);
con.add(s3);
Collection con2 = new ArrayList();
con2.add(Integer.valueOf(1));
con2.add(2);
con2.add(3);
con.addAll(con2);
b/删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素 ,如果没有交集元素 则删除失败 返回false
[Java] 纯文本查看 复制代码 Collection collection = new ArrayList();
<span class="space" style="white-space:pre;display:inline-block;text-indent:2em;line-height:inherit;"> </span>collection.add("关羽");
collection.add("张飞");
collection.add("赵云");
collection.add("马超");
collection.add("魏延");
boolean b = collection.remove("魏延");
[Java] 纯文本查看 复制代码 <span style="background-color:transparent;"> </span>A 集合 removeAll B 集合,如果两个集合没有交集元素,则移除失败
两个集合中的元素都不会发生变化
如果说有交集元素, A 集合 removeAll B 集合 那么A中就会移除掉 交集元素 B集合不发生变化,移除成功
c/判断功能 boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
boolean isEmpty():判断集合是否为空
d/获取功能,接口 Iterator<E> 迭代器(可以理解为遍历)
boolean hasNext()
如果仍有元素可以迭代,则返回 true
[Java] 纯文本查看 复制代码 Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);}
e/长度功能
int size():元素的个数
f/交集功能
A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化
boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
g/把集合转换为数组
toArray( ) System.out.println(collection.size());
[Java] 纯文本查看 复制代码 Collection collection = new ArrayList();
collection.add(1);
collection.add(2);
collection.add(3);
collection.add(4);
collection.add(5);
collection.add(6);
Object[] toArray();
Object[] objects = collection.toArray();
但是要注意的是通过aslist方法把数组转换成集合后,这个集合就不能再添加元素了
[Java] 纯文本查看 复制代码 Integer[] integers = {1, 2, 3, 7};
List<Integer> integers1 = Arrays.asList(integers);
// integers1.remove(1);//报错
//integers1.add(6);//报错
Collection 集合 对应一个工具类 Collections[Java] 纯文本查看 复制代码 ArrayList<Integer> list = new ArrayList<>();
list.add(3);
list.add(6);
list.add(5);
list.add(2);
list.add(1);
list.add(9);
list.add(10);
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer s1, Integer s2) {
return s1 - s2;
}
};
//Lambda 表达式 需要 函数式接口的支持,使用Lambda表达式可以有效的的节省代码,但应用时一定要细心将表达式补充完整。
//函数式接口 接口里面只有一个抽象方法就是函数式接口
// Comparator<Integer> com = (x, y) -> x - y;
//Lambda 表达式 要一种函数式接口的支持 排序
list.sort(comparator);
Collections.sort(list);
System.out.println(list);
二分查找,前提是集合的元素有序
int i = Collections.binarySearch(list, 10);
System.out.println(i);
获取集合中 最大值和最小值
Integer max = Collections.max(list);
Integer min = Collections.min(list);
反转集合中的元素
Collections.reverse(list);
System.out.println(list);
随机打乱集合中的元素顺序
Collections.shuffle(list);
System.out.println(list);
接口 Iterator<E>
通过迭代器是遍历集合的一种方式
boolean hasNext()
如果仍有元素可以迭代,则返回 true。
next()
返回迭代的下一个元素。
[Java] 纯文本查看 复制代码 Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);}
获取集合长度的方法 size()System.out.println(collection.size());
虽然集合可以存储任意数据的引用数据类型但一般来说,我们不会给集合中存储的多种类型的元素,我们一般只在集合里面就存储一种类型
List集合: 包括 ArrayList Vector LinkedList允许元素重复
void add(int index,E element): 在指定索引处添加元素
E remove(int index):移除指定索引处的元素 返回的是移除的元素
E get(int index):获取指定索引处的元素
E set(int index,E element):更改指定索引处的元素 返回的而是被替换的元素
subList(首索引,尾索引),根据首位索引截取集合中的元素
List的三个子类的特点 ArrayList 底层数据结构是数组,增删慢,查询快 线程不同步,数据不安全,效率高
Vector 底层数据结构也是数组,增删慢 查询快 线程同步,数据安全,效率慢
LinkedList 底层数据结构是链表,增删快 查询慢 线程不同步,数据不安全效率高
我们根据需要,如果对数据安全要求较高,建议采用Vector
还要考虑操作中查询多还是增删多
数组特点: 查询快 , 增删慢
链表特点: 查询慢 , 增删快
ListIteratorListIterator继承了Iterator,所以也可以使用Iterator中的方法
而ListIterator的特有功能有
boolean hasPrevious(): 是否存在前一个元素
E previous(): 返回列表中的前一个元素
用这两个方法反向遍历集合
因为指针默认在集合开始,只有先将指针放到末尾才能反向遍历
[Java] 纯文本查看 复制代码 ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()){
System.out.println( iterator.next());
}
System.out.println("---------------------");
while (iterator.hasPrevious()){
System.out.println(iterator.previous())
List集合的遍历方式
如果说你用迭代器去遍历集合,在遍历的中间,如果你想往集合里面加元素,或者说删除元素
那就要用迭代器自己的 添加和删除方法,不要用集合的添加和删除方法,不然就会报并发修改异常,//ConcurrentModificationException,所以经常采用for循环来遍历
[Java] 纯文本查看 复制代码 方式1:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("----------------------------------------");
方式2:采用List 特有的迭代器
ListIterator<String> stringListIterator = list.listIterator();
while (stringListIterator.hasNext()) {
System.out.println(stringListIterator.next());
}
System.out.println("----------------------------");
方式3:for 循环遍历//我们最常用for循环来遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
ArrayList他的底层数据结构是数组,所以 查询快,增删慢
数据是有序的,存的顺序和取得顺序一样
[Java] 纯文本查看 复制代码 ArrayList<String> list = new ArrayList<>();
list.add("唐三藏");
list.add("孙大圣");
list.add("猪悟能");
list.add("沙悟净");
list.add("小白龙");
list.add("唐三藏");
list.add("孙大圣");
list.add("猪悟能");
list.add("沙悟净");
list.add("小白龙");
//重新拿出一个集合,遍历第一个集合,去掉重复的元素
ArrayList<String> newList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
String ele = list.get(i);
if (!newList.contains(ele)) {
newList.add(ele);
}
}
System.out.println(newList);
System.out.println(list);
其中contains这个方法底层调用了equals方法,默认比较的是地址值,所以当两个对象相同时,我们要重写equals方法
VectorinsertElementAt(E obj, int index)在指定索引的位置插入一个元素
indexOf(Object o)返回指定元素的一次出现的索引
lastElement()获取集合中最后一个元素
firstElement()获取集合中第一个元素
Vector 特有的一个遍历方式
Enumeration<String> elements = v.elements();
boolean hasMoreElements()
测试此集合是否包含更多元素。
E nextElement()
返回此集合的下一个元素,如果此集合至少有一个元素可以返回。
LinkedListvoid addFirst(E e)在此列表的开始处插入指定的元素。
void addLast(E e)将指定的元素列表的结束。
getFirst()返回此列表中的第一个元素。
getLast()返回此列表中的最后一个元素。
boolean offer(E e)将指定的元素添加到列表的尾部(最后一个元素)。
boolean offerFirst(E e)在列表的前面插入指定的元素。
boolean offerLast(E e)在列表的结尾插入指定的元素。
void push(E e)将一个元素放在集合最前端
Arrays工具类的asList()方法将数组元素转换成集合,得到的集合长度是不可变的 你不能往这个转换后的集合中 添加元素(add) 和 删除元素(remove), 只能获取元素(get)
数据结构的栈和队列
数据结构的数组和链表
set接口:包含HashSet LinkedHashSet TreeSetset集合的特点:元素是无序的,唯一的HashSet(无序,唯一)HashSet集合底层结构是哈希表,哈希表底层维护的是数组和链表
HashSet集合靠元素重写hashCode和equals方法来保证元素的唯一性
元素有序靠链表保证
元素唯一靠哈希表保证
如果元素不重写这两个方法,就无法保证唯一性
String和Integer默认重写了hashCode方法和equals方法
HashSet存储元素保证元素唯一性图解
TreeSet(排序,唯一)TreeSet 底层数据结构是二叉树结构,元素唯一,而且还能排序
二叉树存储数据保证元素唯一性的原理图解
排序的方法有两种
1。自然排序 空参构造采用的就是自然排序
采用自然排序,是元素实现了Comparaeble接口 重写了compareTo方法
如果元素不重写接口中的方法。那么存储元素时就会报错
存元素的时候,根据compareTo方法的返回值来决定
返回0:就不存
返回正数:往树的根节点的右边存
返回负数:往树的根节点的左边存
[Java] 纯文本查看 复制代码 string和Integer默认实现了Compareble和重写了compareTo方法
TreeSet<String> tree = new TreeSet<>();
tree.add("b");
tree.add("a");
tree.add("b");
tree.add("c");
tree.add("d");
tree.add("a");
System.out.println(tree);
2。比较器排序 有参构造采用的就是比较器排序
创建TreeSet对象的时候,传进来一个比较器的子类对象
接口 Comparator<T> 比较器
int compare(T o1, T o2) 比较方法比较用来排序的两个参数
根据子类对象重写比较器中的compare方法,根据方法返回值的正负和0来排序元素和去重
对于自定义类,采用匿名内部类的方法去重写方法传参数比较方便,当然自己定义一个子类也是可以的
[Java] 纯文本查看 复制代码 TreeSet t = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer s1, Integer s2) {
return s1 - s2;
}
});
t.add(6);
t.add(6);
t.add(3);
t.add(2);
t.add(1);
t.add(4);
t.add(5);
t.add(4);
t.add(3);
System.out.println(t);
}//[1,2,3,4,5,6]
LinkedHashSet(有序,唯一)LinkedhashSet 底层数据结构是链表和哈希表
元素有序靠链表保证,元素唯一靠哈希表保证
[Java] 纯文本查看 复制代码 LinkedHashSet<Integer> list = new LinkedHashSet<>();
list.add(Integer.valueOf(1));
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);//[1, 2, 3, 4, 5]
用自然排序:采用自然排序 要求元素必须实现Comparable接口
然后重写compareTo方法 根据自己的排序方式 返回正负或0
用比较器去排序:采用匿名内部类的方式去传入比较器 的子类对象,重写compare方法
接口 Map<K,V>将键映射到值的对象,一个映射不能包含重复的键,每个键最多映射一个值,K为键。V为值。map集合中,一个键只对应一个值,当键相同时值会覆盖,其中允许使用null键与null值,map集合的数据结构只和键有关,与值无关常用方法HashMap<String, String> hm = new HashMap<>(); String put = hm.put("老大", "呵呵");//添加元素
String put2 = hm.put("张三", "哈哈");//键相同,值覆盖
String put3 = hm.put("张三", "呵呵");//输出结果:张三呵呵
hm.remove("老大");//移除一个键值对hm.clear();//清空一个集合boolean b = hm.containsKey("张三");//判断一个集合是否包含指定键
boolean v = hm.containsValue("哈哈");//判断一个集合是否包含指定值
boolean empty = hm.isEmpty();//判断一个集合是否为空
类 HashMap<K,V>允许插入null键和null值HashMap和Hashtable的区别:
HashMap: 非同步,线程不安全,效率高.允许null值和null键
Hashtable: 同步,线程安全 , 效率低.不允许null值和null键
获取所有值的集合
[Java] 纯文本查看 复制代码 Collection<String> values = hm.values();
for(String v:values){
System.out.println(v);
}
获取集合长度hm.size();
遍历集合有两种方法1。通过键来找值
[Java] 纯文本查看 复制代码 Set<Integer> keys = hm.keySet();//获取所有键的集合
for (Integer key : keys) {
String value = hm.get(key);//通过键,获取值
System.out.println(key + "====" + value);
}
2。直接获取 键值对 对象 ,用对象里面的方法获取键跟值
[Java] 纯文本查看 复制代码 Set<Map.Entry<Integer, String>> entries = hm.entrySet();
for (Map.Entry<Integer, String> en : entries) {
System.out.println(en.getKey() + "===" + en.getValue());
}
类 LinkedHashMap<K,V>底层数据结构是链表和哈希表,元素有序且唯一其特点是保存了记录的插入顺序,先得到的记录先插入,LinkedHashMap取的顺序就是自己存的顺序
类 TreeMap<K,V>
TreeMap集合不允许插入null键,可以插入null值TreeMap集合的两种排序方法:自然排序和比较器排序方法与TreeMap大致相同
案例演示:斗地主,经常拿来看看,复习一下
使用ArrayList
[Java] 纯文本查看 复制代码 package org.westos.demo4;
import java.util.ArrayList;
import java.util.Collections;
public class MyTest7 {
public static void main(String[] args) {
//模拟斗地主的发牌和看牌
// 模拟斗地主洗牌和发牌,牌没有排序
//1.定义一个牌盒 来装牌
//2.生成54张牌装进牌盒
//3.洗牌
//4.发牌
//5.看牌
//1.创建牌盒子
ArrayList<String> pokerBox = new ArrayList<>();
//2.生成牌 ,装进牌盒
String[] colors = {"♣", "♠", "♥", "◆"};
String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
for (String color : colors) {
for (String num : nums) {
String pai = color.concat(num);
pokerBox.add(pai);
}
}
//添加大小王
pokerBox.add("★");
pokerBox.add("☆");
//洗牌
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
// System.out.println(pokerBox);
// 发牌
ArrayList<String> 底牌 = new ArrayList<>();
ArrayList<String> 周星驰 = new ArrayList<>();
ArrayList<String> 吴宗宪 = new ArrayList<>();
ArrayList<String> 曾志伟 = new ArrayList<>();
//发牌的算法
// 周星驰 0 3 6 9
//// 吴宗宪 1 4 7 10
//// 曾志伟 2 5 8 11
for (int i = 0; i < pokerBox.size(); i++) {
//留底牌
if (i >=pokerBox.size() - 3) {
底牌.add(pokerBox.get(i));
} else if (i % 3 == 0) {
周星驰.add(pokerBox.get(i));
} else if (i % 3 == 1) {
吴宗宪.add(pokerBox.get(i));
} else if (i % 3 == 2) {
曾志伟.add(pokerBox.get(i));
}
}
//看牌
lookPoker("周星驰",周星驰);
lookPoker("吴宗宪",吴宗宪);
lookPoker("曾志伟",曾志伟);
lookPoker("底牌",底牌);
}
private static void lookPoker(String name, ArrayList<String> list) {
System.out.println(name);
for(String s:list){
System.out.print(s+" ");
}
System.out.println();
}
}
使用HashMap
[Java] 纯文本查看 复制代码 package org.westos.demo4;
import sun.security.action.PutAllAction;
import java.util.*;
public class MyTest8 {
public static void main(String[] args) {
//创建牌盒
HashMap<Integer, String> pokerBox = new HashMap<>();
//生成牌,往牌盒里面装牌
String[] colors = {"♣", "♠", "♥", "◆"};
String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
int index = 0;//定义索引
for (String num : nums) {
for (String color : colors) {
String poker = num.concat(color);
pokerBox.put(index, poker);
index++;
}
}
//手动添加两张王
pokerBox.put(index, "★");
index++;
pokerBox.put(index, "☆");
//System.out.println(pokerBox);
//洗牌
Set<Integer> integers = pokerBox.keySet();
ArrayList<Integer> suoyin = new ArrayList<>();
for (Integer i : integers) {
suoyin.add(i);
}
// System.out.println(suoyin);
Collections.shuffle(suoyin);
Collections.shuffle(suoyin);
Collections.shuffle(suoyin);
//发牌
TreeSet<Integer> 底牌 = new TreeSet<Integer>();
TreeSet<Integer> 周星驰 = new TreeSet<Integer>();
TreeSet<Integer> 吴宗宪 = new TreeSet<Integer>();
TreeSet<Integer> 曾志伟 = new TreeSet<Integer>();
for (int i = 0; i < suoyin.size(); i++) {
if (i >= suoyin.size() - 3) {
底牌.add(suoyin.get(i));
} else if (i % 3 == 0) {
周星驰.add(suoyin.get(i));
} else if (i % 3 == 1) {
吴宗宪.add(suoyin.get(i));
} else if (i % 3 == 2) {
曾志伟.add(suoyin.get(i));
}
}
//看牌
lookPoker("底牌", 底牌, pokerBox);
lookPoker("周星驰", 周星驰, pokerBox);
lookPoker("吴宗宪", 吴宗宪, pokerBox);
lookPoker("曾志伟", 曾志伟, pokerBox);
}
private static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> pokerBox) {
System.out.println(name);
for (Integer in : ts) {
System.out.print(pokerBox.get(in));
}
System.out.println();
}
}
|