1、Collection(集合)
集合
:集合是
java
中提供的⼀种容器,可以⽤来存储多个数据。
集合与数组的区别:
- 数组的长度是固定的,集合的长度是可变的。
-
数组中存储的是同⼀类型的元素,可以存储基本数据类型值。集合存储的都是对象。⽽且对象的类型可以不⼀致。在开发中⼀般当对象多的时候,使⽤集合进⾏存储。
集合本身是⼀个⼯具,它存放在
java.util
包中。集合按照其存储结构可以分为两⼤类,分别是单列集合 java.util.Collection
和双列集合java.util.Map。
Collection
:单列集合类的根接⼝,⽤于存储⼀系列符合某种规则的元素,它有两个重要的⼦接⼝,分别是 java.util.List
和
java.util.Set
。其中,
List
的特点是元素有序、元素可重复。 Set
的特点是元素⽆序,⽽且不可重复。
List
接⼝的主要实现类有 java.util.ArrayList
和
java.util.LinkedList
,
Set
接⼝的主要实现类有 java.util.HashSet
和
java.util.TreeSet
。
2.集合常用方法
Collection
是所有单列集合的父接⼝,因此在Collection
中定义了单列集合(
List
和
Set
)通⽤的⼀
些方法,这些方法可⽤于操作所有的单列集合。
1.常用API:
public boolean add(E e)
: 把给定的对象添加到当前集合中 。
public void clear()
:清空集合中所有的元素。
public boolean remove(E e)
:把给定的对象在当前集合中删除。
public boolean contains(E e)
:判断当前集合中是否包含给定的对象。
public boolean isEmpty()
:判断当前集合是否为空。
public int size()
:返回集合中元素的个数。
public Object[] toArray()
:把集合中的元素,存储到数组中。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo01 {
public static void main(String[] args) {
Collection collection = new ArrayList();//向上造型
collection.add(1);
collection.add(2.111);
collection.add("你好");
collection.add(false);
System.out.println(collection);// [1, 2.111, 你好, false]
//询问有无指定元素 boolean contains(Object o)
boolean c1 = collection.contains(1);//询问有无1这个元素
System.out.println(c1);//true
//该集合长度 int size()
int size = collection.size();
System.out.println(size);
//删除指定元素
collection.remove(1);
System.out.println(collection);//[2.111, 你好, false]
//清除所有元素
collection.clear();
System.out.println(collection);//[]
}
}
import java.util.ArrayList;
import java.util.Collection;
/*
Collection常用API:
boolean addAll(Collection<? extends E> c)
boolean containsAll(Collection<?> c)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)
*/
public class CollectionDemo02 {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add("张飞");
col.add("马超");
col.add("关羽");
col.add("赵云");
col.add("黄忠");
Collection col1 = new ArrayList<>();
col1.add("小乔");
col1.add("大乔");
col.addAll(col1);
System.out.println(col);
Collection col2 = new ArrayList<>();
col2.add("张飞");
col2.add("大乔");
//原集合:[张飞, 马超, 关羽, 赵云, 黄忠, 小乔, 大乔]
boolean b = col.containsAll(col2);
System.out.println(b);//ture
//删除col中col2存在的元素
//col.removeAll(col2);
//[张飞, 马超, 关羽, 赵云, 黄忠, 小乔]
System.out.println(col);
Collection col3 = new ArrayList<>();
col3.add("马超");
col3.add("张飞");
boolean b1 = col.retainAll(col3);
System.out.println(b1);//true
System.out.println(col);
}
}
import java.util.ArrayList;
import java.util.Collection;
/*
remove() 和 removeAll()
*/
public class CollectionDemo03 {
public static void main(String[] args) {
Collection col = new ArrayList<>();
col.add("张飞");
col.add("刘备");
col.add("关羽");
col.add("张飞");
System.out.println(col);
//[张飞, 刘备, 关羽, 张飞]
col.remove("张飞");
System.out.println(col);
//[刘备, 关羽, 张飞] 这个是删除从元素最开始寻找删除指定元素一个
Collection col1 = new ArrayList<>();
col1.add("张飞");
col.removeAll(col1);
System.out.println(col);
//[刘备, 关羽] all是删除所有的一样的指定元素
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
/* 集合转换成数组:
Object[] toArray()
<T> T[] toArray(T[] a)
*/
public class CollectionDemo04 {
public static void main(String[] args) {
Collection<Object> col = new ArrayList<>();
col.add(1);
col.add(3.14);
col.add(new Date());
Object[] o = col.toArray();
System.out.println(Arrays.toString(o));
Collection<String> col1 = new ArrayList<>();
col1.add("张三");
col1.add("李四");
col1.add("王五");
/*
toArray(): 永远只能返回Object类型
*/
///*String*/Object s = col1.toArray();
/*
参数: 只是需要数组的类型
和数组的长度无关
*/
String[] str = col1.toArray(new String[0]);
System.out.println(Arrays.toString(str));
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/*
数组转集合:
Arrays.asList()
*/
public class CollectionDemo05 {
public static void main(String[] args) {
Integer[] arr = {1,2,3,4,45};
System.out.println(Arrays.toString(arr));
//数组转集合
/*
asList() -> 获取到的集合 ArrayList,
是在于Arrays类中作为静态内部类存在
又因为数组长度不可变,所以改变数组长度的操作都不支持
*/
Collection col = Arrays.asList(arr);
System.out.println(col);
//修改数组中的元素
arr[1] = 77;
//在col集合中添加元素
//UnsupportedOperationException - 不支持的操作异常
//col.add(88);
System.out.println(col);
//可以通过一个集合构建另一个集合
ArrayList<Object> list = new ArrayList<>(col);
list.add(88);
System.out.println(list);
}
}
2.Iterator迭代器
1、Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,
JDK
专⻔提供了⼀个接⼝
java.util.Iterator
。
Iterator
接⼝也是
Java
集合中的⼀员,但它与
Collection
、
Map
接⼝有所不同, Collection
接⼝与
Map
接⼝主要⽤于存储元素,⽽
Iterator
主要⽤于迭代访问(即遍历) Collection
中的元素,因此
Iterator
对象也被称为迭代器。
获取迭代器的方法:
public Iterator iterator()
:获取集合对应的迭代器,⽤来遍历集合中的元素的。
Iterator
接⼝的常⽤⽅法如下:
public E next()
:返回迭代的下⼀个元素。
public boolean hasNext()
:如果仍有元素可以迭代,则返回
true
。
2、增强版迭代器(for each)
增强
for
循环(也称
for each
循环),是
JDK1.5
以后出来的⼀个⾼级
for
循环,专⻔⽤来遍历数组和集合的。它的内部原理其实是个Iterator
迭代器,所以在遍历的过程中,不能对集合中的元素进⾏增删操作。
for
(
元素的数据类型
变量
:
Collection
集合
or
数组
) {
//
写操作代码
}
它⽤于遍历
Collection
和数组。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
//Iterator迭代器的使用
//因为Collection没有get方法,所以用迭代器获取元素
public class IteratorDemo {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add("mimi");
col.add(12);
col.add(1.22);
col.add(new Date());
System.out.println(col);//[mimi, 12, 1.22, Thu Jul 29 18:47:59 CST 2021]
/*
public E next() :返回迭代的下一个元素。
public boolean hasNext() :如果仍有元素可以迭代,则返回 true。
remove() - 删除集合元素
注意:如果迭代删除每一个元素,
就必须使用迭代器方式进行删除否则会出现ConcurrentModificationException - 并发修改异常
*/
//创建迭代器对象
Iterator it = col.iterator();
//System.out.println(it.next());
//System.out.println(it.hasNext());
while (it.hasNext()){//判断是否有元素可以迭代
Object obj = it.next();//返回一个迭代的元素给一个obj的类型
System.out.println(obj);//输出
/*
mimi
12
1.22
Thu Jul 29 19:05:13 CST 2021
*/
it.remove();
System.out.println(col);//[]
}
//加强版迭代器 for each
Collection col1 = new ArrayList();
col1.add(444);
col1.add("hhhhhh");
col1.add(2.36);
for (Object o:col1) {
System.out.println(o);
}
/*
* 444
* hhhhhh
* 2.36
* */
}
}
3.泛型<>
在前⾯学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object
类型。当我们在取出每⼀个对象,并且进⾏相应的操作,这时必须采⽤类型转换。
Collection
虽然可以存储各种对象,但实际上通常
Collection
只存储同⼀类型对象。例如都是存储字符串对象。因此在JDK5
之后,新增了
泛型
(
Generic
)
语法,让你在设计
API
时可以指定类或⽅法⽀持泛型,这样我们使⽤API
的时候也变得更为简洁,并得到了编译时期的语法检查。
泛型
:本质是参数化类型,可以在类或⽅法中预知地使⽤未知的类型。
Tips
:⼀般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为
Object
类型。
1、特点
a.所有是类型的地方都可以使用泛型来代替,泛型表示所有类型(Object)
b.规定了泛型,就只是支持定义好的类型,只是在编译时有效,用来规范程序员写法。
c.运行时,还是支持Object类型。
2、作用
1.将运⾏时期的
ClassCastException
,转移到了编译时期变成了编译失败。
2.避免了类型强转的麻烦。
3、定义使用
修饰符
class
类名
<
代表泛型的变量
>
{ }
Collection<E> col = new ArrayList();
ArrayList<String> list = new ArrayList<String>();
此时,变量
E
的值就是
String
类型。
泛型作为返回值类型
修饰符
<
代表泛型的变量
>
返回值类型
⽅法名
(
参数
){ }
泛型作为方法参数
修饰符
返回值类型
⽅法名
(
<
代表泛型的变量
>
参数
){ }
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
泛型:支持所有类型(Object)
编译时状态:只是为了规范程序员的写法
运行时状态:底层下支持所有类型(Object)
xx.java -> 编译器 -> xx.class -> (类加载器) -> JVM内存运行
xx.java : 程序员编写的
xx.class: JVM内存运行
*/
public class Demo01 {
public static void main(String[] args) {
Collection<String> col = new ArrayList<>();
//col.add(1);//只能添加String类型的字符串
col.add("呵呵");
col.add("haha");
col.add("xixi");
System.out.println(col);
//[hehe, haha, xixi, 1]
Iterator<String> it = col.iterator();
while (it.hasNext()){
//ClassCastException - 类型转换异常
String s = it.next();
System.out.println(s);
}
}
}
/*
有意义的实体类
*/
public class Student<T,S> {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/*
泛型作为方法参数使用
*/
public void sleep(T a, T b){
System.out.println("睡觉"+a+b);
}
/*
泛型作为返回值类型使用
*/
public T eat(){
System.out.println("干饭");
return null;
}
/*
泛型有两个类型<T,S> : 每一个都是表示Object
*/
public void m1(T t, S s){
System.out.println("m1"+t+s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
public class Demo02 {
public static void main(String[] args) {
Collection<Student> col = new ArrayList<>();//含泛型的类
Student stu1 = new Student("小红",18);
Student<String,Integer> stu2 = new Student("55",18);
col.add(stu1);
col.add(stu2);
System.out.println(col);
//[Student{name='小红', age=18}, Student{name='55', age=18}]
stu1.sleep(1,new Date());
//睡觉1Thu Jul 29 20:08:35 CST 2021
stu1.sleep(3.14,false);
//睡觉3.14false
Object eat = stu1.eat();
stu1.m1(2,"33");
//m1233
//remove()
col.remove(stu1);
System.out.println(col);
//[Student{name='55', age=18}]
}
}
斗地主发牌取牌实现
//斗地主游戏
/*按照斗地主的规则,完成洗牌发牌的动作。
具体规则:
使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。*/
import java.util.ArrayList;
import java.util.Collections;
public class Poker {
public static void main(String[] args) {
ArrayList<String> colors = new ArrayList<>();
ArrayList<String> nums = new ArrayList<>();
ArrayList<String> cards = new ArrayList<>();
//花色
colors.add("方块");
colors.add("梅花");
colors.add("红心");
colors.add("黑桃");
//遍历卡牌数字
for (int i = 2; i < 10; i++) {
nums.add( i+ "");
}
nums.add("A");
nums.add("J");
nums.add("Q");
nums.add("K");
//大小王2张
cards.add("bigJoker");
cards.add("smallJoker");
for (String color : colors) {
for (String num : nums) {
String card = color + num;
cards.add(card);//将遍历出来的花色加牌号添加到卡牌集合中
}
}
System.out.println(cards);
Collections.shuffle(cards);//打乱牌的顺序
//创建玩家
ArrayList<String> player01 = new ArrayList<String> ();
ArrayList<String> player02 = new ArrayList<String> ();
ArrayList<String> player03 = new ArrayList<String> ();
//底牌3张
ArrayList<String> gameCard = new ArrayList<String> ();
for (int i = 0; i < cards.size(); i++) {
String card = cards.get(i);
if (i >= cards.size()-3){
gameCard.add(card);
}else{
if (i%3==0){
player01.add(card);
}else if (i%3==1){
player02.add(card);
}else{
player03.add(card);
}
}
}
System.out.println("玩家一号"+player01.size()+"张牌"+player01);
System.out.println("玩家二号"+player02.size()+"张牌"+player02);
System.out.println("玩家三号"+player03.size()+"张牌"+player03);
System.out.println("底牌"+gameCard);
}
}