Collection集合,Iterator迭代器,泛型
一、Collection集合
A.数组(存放任意类型,长度固定)
B.集合(存放对象类型,长度可变)
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素。
- 它有两个重要的子接口,分别是
java.util.List
和java.util.Set
。 - 其中,
List
的特点是元素有序、元素可重复。Set
的特点是元素无序,而且不可重复。 List
接口的主要实现类有java.util.ArrayList
和java.util.LinkedList
Set
接口的主要实现类有java.util.HashSet
和java.util.TreeSet
。
1.Collection 常用功能
Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:
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 Test {
public static void main(String[] args) {
Collection<String> str1=new ArrayList();
//add添加元素
str1.add("一一");
str1.add("二二");
str1.add("三三");
str1.add("四四");
System.out.println(str1); //[一一, 二二, 三三, 四四]
//remove删除元素
str1.remove("一一");
System.out.println(str1); //[二二, 三三, 四四]
//contains判断一个元素是否在该集合中
boolean a = str1.contains("二二");
System.out.println(a); //true
//size()看集合中有多少个元素(就是看长度)
int a2 = str1.size();
System.out.println(a2); //3
//toArray()转换成一个Object数组
Object[] obj = str1.toArray();
//遍历数组
for (int i = 0; i < obj.length; i++) {
System.out.println(obj[i]);
} //二二 三三 四四
//或者想创建一个String类型的数组
//格式: String [] 对象名=new String[集合的长度];
//集合对象名.toArray(String类型数组的对象名); 再遍历数组
String [] arr=new String[str1.size()];
str1.toArray(arr);
//遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
} //二二 三三 四四
//isEmpty()判断当前集合是否为空
boolean a3 = str1.isEmpty();
System.out.println(a3); //false
//clear() 清空集合
str1.clear();
System.out.println(str1); //[]
//清空元素后再次用isEmpty()判断当前集合是否为空
boolean a4 = str1.isEmpty();
System.out.println(a4); //true
}
}
二、Iterator迭代器
1.Iterator接口
迭代的概念:
- 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
public E next()
:返回迭代的下一个元素。public boolean hasNext()
:如果仍有元素可以迭代,则返回 true。
2.增强for
增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
三种遍历集合的方法:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
Collection<String> str1=new ArrayList<>();
str1.add("aa");
str1.add("bb");
str1.add("cc");
str1.add("dd");
System.out.println(str1);
System.out.println("========转数组========");
String [] str2=new String[str1.size()];
str1.toArray(str2);
for (int i = 0; i < str2.length; i++) {
System.out.println(str2[i]+","+str2[i].toUpperCase());
}
System.out.println("========迭代器========");
Iterator<String> str3 = str1.iterator();
while (str3.hasNext()){
String str4 = str3.next();
System.out.println(str4+","+str4.toUpperCase());
}
System.out.println("========增强for========");
int count = 0;
for (String s : str1) {
System.out.println(s+","+s.toUpperCase());
}
}
}
/*给定以下代码,请定义方法
public static int listTest(Collection<String> list,String s)
统计集合中指定元素出现的次数,如"a":2,"b": 2,"c" :1, "xxx":0。
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.println("a:"+listTest(list, "a"));
System.out.println("b:"+listTest(list, "b"));
System.out.println("c:"+listTest(list, "c"));
System.out.println("xxx:"+listTest(list, "xxx"));*/
//练习
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.print("a:" + listTest(list, "a")+",");
System.out.print("b:" + listTest(list, "b")+",");
System.out.print("c:" + listTest(list, "c")+",");
System.out.print("xxx:" + listTest(list, "xxx")+"。");
}
public static int listTest(Collection<String> list, String s) {
Iterator<String> str1 = list.iterator();
int count = 0;
while (str1.hasNext()) {
String str2 = str1.next();
if (str2.equals(s)) {
count++;
}
}
//System.out.println(s + ":" + count);
return count;
}
}
//输出结果:a:2,b:2,c:1,xxx:0。
简单的斗地主案例
import java.util.ArrayList;
import java.util.Collections;
public class Test {
public static void main(String[] args) {
//1.准备牌
ArrayList<String> zong=new ArrayList<>();
zong.add("大王");
zong.add("小王");
String[] huase = {"♣","♦","❤","♠"};
String[] shuzi = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
for (String s : huase) {
for (String s1 : shuzi) {
zong.add(s+s1);
}
}
//2.洗牌,随机排序
Collections.shuffle(zong);
//3.发牌
ArrayList<String> wj1=new ArrayList<>();
ArrayList<String> wj2=new ArrayList<>();
ArrayList<String> wj3=new ArrayList<>();
ArrayList<String> dipai=new ArrayList<>();
for (int i = 0; i < zong.size(); i++) {
String p = zong.get(i);
if(i>=51){
dipai.add(p);
}else if(i%3==0){
wj1.add(p);
}else if(i%3==1){
wj2.add(p);
}else if(i%3==2){
wj3.add(p);
}
}
//4.看牌
System.out.println("1号的牌:"+wj1);
//1号的牌:[❤4, ♠5, ♦Q, ❤Q, ♠4, ♦6, ♦K, ♣7, ♣K, ♣9, ♦3, ♣J, ♦2, ♣3, ♣8, ❤8, 小王]
System.out.println("2号的牌:"+wj2);
//2号的牌:[♣5, ♦9, ♦7, ❤6, ♠8, ❤5, ♦A, ♠6, ♣10, ♦10, ♠2, ♠3, ♠7, ♠9, ♦5, ♣6, ♠K]
System.out.println("3号的牌:"+wj3);
//3号的牌:[♦4, ♣A, ♠J, ♣Q, ❤9, 大王, ❤3, ♠A, ❤J, ♠Q, ♣4, ❤2, ♦J, ❤A, ❤K, ❤10, ♣2]
System.out.println("底牌:"+dipai);
//底牌:[❤7, ♦8, ♠10]
//在运行一次结果就不同,因为是随机的
}
}
三、泛型
1.使用泛型的好处
- 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
- 避免了类型强转的麻烦。
2.泛型的定义与使用
A.定义和使用含有泛型的类
定义格式:
修饰符 class 类名<代表泛型的变量> { }
自定义泛型的类
//定义泛型类
public class ZiDinYi<s> {
private s name;
private s name2;
public s getName2() {
return name2;
}
public void setName2(s name2) {
this.name2 = name2;
}
public s getName() {
return name;
}
public void setName(s name) {
this.name = name;
}
}
使用
public class Test {
public static void main(String[] args) {
//创建对象不定义泛型,是Object
ZiDinYi zdy=new ZiDinYi();
zdy.setName("随便传");
zdy.setName2(222);
Object a1 = zdy.getName();
Object a = zdy.getName2();
System.out.println("a1 = " + a1+a);//a1 = 随便传222
System.out.println("==============");
//创建对象定义泛型,String类
ZiDinYi<String> zdy2=new ZiDinYi<>();
zdy2.setName("String类型");
zdy2.setName2("必须定义成String类型");
String a2 = zdy2.getName();
System.out.println("a2 = " + a2);//a2 = String类型
System.out.println(zdy2.getName2());//必须定义成String类型
System.out.println("==============");
//创建对象定义泛型,Integer类
ZiDinYi<Integer> zdy3=new ZiDinYi<>();
zdy3.setName(234);
Integer a3 = zdy3.getName();
System.out.println("a3 = " + a3);//a3 = 234
}
}
B.含有泛型的方法
定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
class MyAeeay{
//定义泛型方法
//定义方法(静态)
public <W> void fangFa1(W w){
System.out.println(w);
}
//定义方法(静态)
public static <W> void fangFa2(W w){
System.out.println(w);
}
}
//使用
public class Test {
public static void main(String[] args) {
MyAeeay ma=new MyAeeay();
ma.fangFa1("asas");//asas
ma.fangFa1(123);//123
System.out.println("==========");
//调用静态方法直接 类名称.方法名
MyAeeay.fangFa2("iuuy");//iuuy
MyAeeay.fangFa2(78);//78
}
}
C.含有泛型的接口
定义格式:
修饰符 interface接口名<代表泛型的变量> { }
定义接口
public interface MyInter <M>{
public abstract void jieKou(M m);
}
实现类
//定义实现类
//在类名称和接口后都要加上泛型
public class ShiXian<M> implements MyInter<M> {
@Override
public void jieKou(M m) {
System.out.println(m);
}
}
使用
public class Test {
public static void main(String[] args) {
//1.不使用泛型,默认Object类
ShiXian a1=new ShiXian();
a1.jieKou("张");//张
a1.jieKou(1997);//1997
System.out.println("=========");
//2.使用泛型 String类
ShiXian<String> a2=new ShiXian<>();
a2.jieKou("三");//三
System.out.println("=========");
//3.使用泛型 Integer类
ShiXian<Integer> a3=new ShiXian<>();
a3.jieKou(1117);//1117
}
}
小练习:编写一个泛型方法,实现任意引用类型数组指定位置元素交换
import java.util.ArrayList;
import java.util.Collection;
class Lei {
public <E> void fangFa(E[] e, int a, int b) {
//用泛型E来当第三个数接收
E tmp = e[a];
e[a] = e[b];
e[b] = tmp;
for (E e1 : e) {
System.out.print(e1 + " ");
}
}
}
public class Test {
public static void main(String[] args) {
Lei l=new Lei();
Integer[] i={1,2,3,4,5};
String[] str1={"x","y","z","q"};
l.fangFa(str1,0,2);
System.out.println();
l.fangFa(i,1,3);
}
}