【Java】Collection集合&泛型(二)

简介: 本期主要介绍Collection集合&泛型

3.2 使用泛型的好处


上一节只是讲解了泛型的引入,那么泛型带来了哪些好处呢?

  • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
  • 避免了类型强转的麻烦。

通过我们如下代码体验一下:

publicclassGenericDemo2 {
publicstaticvoidmain(String[] args) {
Collection<String>list=newArrayList<String>();
list.add("abc");
list.add("itcast");
// list.add(5);//当集合明确类型后,存放类型不一致就会编译报错// 集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型Iterator<String>it=list.iterator();
while(it.hasNext()){
Stringstr=it.next();
//当使用Iterator<String>控制元素类型后,就不需要强转了。获取到的元素直接就是String类型System.out.println(str.length());
        }
    }
}

tips:泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。

3.3 泛型的定义与使用


我们在集合中会大量使用到泛型,这里来完整地学习泛型知识。

泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

定义和使用含有泛型的类


定义格式:

修饰符 class 类名<代表泛型的变量> {  }

例如,API中的ArrayList集合:

classArrayList<E>{ 
publicbooleanadd(Ee){ }
publicEget(intindex){ }
    ....
}

使用泛型: 即什么时候确定泛型。

在创建对象的时候确定泛型

例如,ArrayList<String> list = new ArrayList<String>();

此时,变量E的值就是String类型,那么我们的类型就可以理解为:

classArrayList<String>{ 
publicbooleanadd(Stringe){ }
publicStringget(intindex){  }
     ...
}

再例如,ArrayList<Integer> list = new ArrayList<Integer>();

此时,变量E的值就是Integer类型,那么我们的类型就可以理解为:

classArrayList<Integer> { 
publicbooleanadd(Integere) { }
publicIntegerget(intindex) {  }
     ...
}

举例自定义泛型类

publicclassMyGenericClass<MVP> {
//没有MVP类型,在这里代表 未知的一种数据类型 未来传递什么就是什么类型privateMVPmvp;
publicvoidsetMVP(MVPmvp) {
this.mvp=mvp;
    }
publicMVPgetMVP() {
returnmvp;
    }
}

使用:

publicclassGenericClassDemo {
publicstaticvoidmain(String[] args) {         
// 创建一个泛型为String的类MyGenericClass<String>my=newMyGenericClass<String>();      
// 调用setMVPmy.setMVP("大胡子登登");
// 调用getMVPStringmvp=my.getMVP();
System.out.println(mvp);
//创建一个泛型为Integer的类MyGenericClass<Integer>my2=newMyGenericClass<Integer>(); 
my2.setMVP(123);         
Integermvp2=my2.getMVP();
    }
}

含有泛型的方法


定义格式:

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){  }

例如,

publicclassMyGenericMethod {    
public<MVP>voidshow(MVPmvp) {
System.out.println(mvp.getClass());
    }
public<MVP>MVPshow2(MVPmvp) {   
returnmvp;
    }
}

使用格式:调用方法时,确定泛型的类型

publicclassGenericMethodDemo {
publicstaticvoidmain(String[] args) {
// 创建对象MyGenericMethodmm=newMyGenericMethod();
// 演示看方法提示mm.show("aaa");
mm.show(123);
mm.show(12.45);
    }
}

含有泛型的接口


定义格式:

修饰符 interface接口名<代表泛型的变量> {  }

例如,

publicinterfaceMyGenericInterface<E>{
publicabstractvoidadd(Ee);
publicabstractEgetE();  
}

使用格式:

1、定义类时确定泛型的类型

例如

publicclassMyImp1implementsMyGenericInterface<String> {
@Overridepublicvoidadd(Stringe) {
// 省略...    }
@OverridepublicStringgetE() {
returnnull;
    }
}

此时,泛型E的值就是String类型。

2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型

例如

publicclassMyImp2<E>implementsMyGenericInterface<E> {
@Overridepublicvoidadd(Ee) {
// 省略...    }
@OverridepublicEgetE() {
returnnull;
    }
}
//确定泛型:/** 使用*/publicclassGenericInterface {
publicstaticvoidmain(String[] args) {
MyImp2<String>my=newMyImp2<String>();  
my.add("aa");
    }
}

3.4 泛型通配符


当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object

类中的共性方法,集合中元素自身方法无法使用。

通配符基本使用

泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

此时只能接受数据,不能往该集合中存储数据。

举个例子大家理解使用即可:

publicstaticvoidmain(String[] args) {
Collection<Intger>list1=newArrayList<Integer>();
getElement(list1);
Collection<String>list2=newArrayList<String>();
getElement(list2);
}
publicstaticvoidgetElement(Collection<?>coll){}
//?代表可以接收任意类型

tips:泛型不存在继承关系 Collection<Object> list = new ArrayList<String>();这种是错误的。

通配符高级使用----受限泛型

之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限下限

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义只能接收该类型及其子类

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义只能接收该类型及其父类型

比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类

publicstaticvoidmain(String[] args) {
Collection<Integer>list1=newArrayList<Integer>();
Collection<String>list2=newArrayList<String>();
Collection<Number>list3=newArrayList<Number>();
Collection<Object>list4=newArrayList<Object>();
getElement(list1);
getElement(list2);//报错getElement(list3);
getElement(list4);//报错getElement2(list1);//报错getElement2(list2);//报错getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类publicstaticvoidgetElement1(Collection<?extendsNumber>coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类publicstaticvoidgetElement2(Collection<?superNumber>coll){}

第四章 集合综合案例


4.1 案例介绍


按照斗地主的规则,完成洗牌发牌的动作。 具体规则:

使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。

4.2 案例分析


  • 准备牌:
  • 牌可以设计为一个ArrayList<String>,每个字符串为一张牌。 每张牌由花色数字两部分组成,我们可以使用花色集合与数字集合嵌套迭代完成每张牌的组装。 牌由Collections类的shuffle方法进行随机排序。
  • 发牌将每个人以及底牌设计为ArrayList<String>,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。
  • 看牌
    直接打印每个集合。

4.3 代码实现


importjava.util.ArrayList;
importjava.util.Collections;
publicclassPoker {
publicstaticvoidmain(String[] args) {
/** 1: 准备牌操作*///1.1 创建牌盒 将来存储牌面的 ArrayList<String>pokerBox=newArrayList<String>();
//1.2 创建花色集合ArrayList<String>colors=newArrayList<String>();
//1.3 创建数字集合ArrayList<String>numbers=newArrayList<String>();
//1.4 分别给花色 以及 数字集合添加元素colors.add("♥");
colors.add("♦");
colors.add("♠");
colors.add("♣");
for(inti=2;i<=10;i++){
numbers.add(i+"");
        }
numbers.add("J");
numbers.add("Q");
numbers.add("K");
numbers.add("A");
//1.5 创造牌  拼接牌操作// 拿出每一个花色  然后跟每一个数字 进行结合  存储到牌盒中for (Stringcolor : colors) {
//color每一个花色 //遍历数字集合for(Stringnumber : numbers){
//结合Stringcard=color+number;
//存储到牌盒中pokerBox.add(card);
            }
        }
//1.6大王小王pokerBox.add("小☺");
pokerBox.add("大☠");   
// System.out.println(pokerBox);//洗牌 是不是就是将  牌盒中 牌的索引打乱 // Collections类  工具类  都是 静态方法// shuffer方法   /** static void shuffle(List<?> list) *     使用默认随机源对指定列表进行置换。 *///2:洗牌Collections.shuffle(pokerBox);
//3 发牌//3.1 创建 三个 玩家集合  创建一个底牌集合ArrayList<String>player1=newArrayList<String>();
ArrayList<String>player2=newArrayList<String>();
ArrayList<String>player3=newArrayList<String>();
ArrayList<String>dipai=newArrayList<String>();    
//遍历 牌盒  必须知道索引   for(inti=0;i<pokerBox.size();i++){
//获取 牌面Stringcard=pokerBox.get(i);
//留出三张底牌 存到 底牌集合中if(i>=51){//存到底牌集合中dipai.add(card);
            } else {
//玩家1   %3  ==0if(i%3==0){
player1.add(card);
                }elseif(i%3==1){//玩家2player2.add(card);
                }else{//玩家3player3.add(card);
                }
            }
        }
//看看System.out.println("令狐冲:"+player1);
System.out.println("田伯光:"+player2);
System.out.println("绿竹翁:"+player3);
System.out.println("底牌:"+dipai);  
    }
}
相关文章
|
1天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
7 2
|
1天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
5天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
5天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
5天前
|
Java 开发者
|
18天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
47 5
|
16天前
|
Java API
[Java]泛型
本文详细介绍了Java泛型的相关概念和使用方法,包括类型判断、继承泛型类或实现泛型接口、泛型通配符、泛型方法、泛型上下边界、静态方法中使用泛型等内容。作者通过多个示例和测试代码,深入浅出地解释了泛型的原理和应用场景,帮助读者更好地理解和掌握Java泛型的使用技巧。文章还探讨了一些常见的疑惑和误区,如泛型擦除和基本数据类型数组的使用限制。最后,作者强调了泛型在实际开发中的重要性和应用价值。
14 0
[Java]泛型
|
19天前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
47 3
|
5天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
7 0
|
10天前
|
Java API Apache
java集合的组内平均值怎么计算
通过本文的介绍,我们了解了在Java中计算集合的组内平均值的几种方法。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。无论是使用传统的循环方法,还是利用Java 8的Stream API,亦或是使用第三方库(如Apache Commons Collections和Guava),都可以有效地计算集合的组内平均值。希望本文对您理解和实现Java中的集合平均值计算有所帮助。
19 0
下一篇
无影云桌面