集合、迭代器、for-each、泛型

学习集合的目标
1. 会使用集合存储数据
2. 会遍历集合,把数据取出来
3.掌握每种集合的特性

在这里插入图片描述在这里插入图片描述

一、集合常用方法

boolean add(E e);   向集合中添加元素
boolean remove(E e);  删除集合中的某个元素
void clear();   清除集合所有的元素
boolean contains(E e);  判断集合中是否包含某个元素
boolean isEmpty();  判读那集合是否为空
int size();     获取集合的长度
Object[] toArray();     将集合转换成一个数组
package com.itheima.demo06;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

public class Test01 {
    public static void main(String[] args) {
        //创建集合对象
        Collection<String> coll = new ArrayList<>();
//        boolean add(E e);   向集合中添加元素
        coll.add("hello");
        coll.add("world");
        coll.add("heima");
        coll.add("java");
        System.out.println(coll); //[hello,world,heima,java]

        //boolean remove(E e);  删除集合中的某个元素
        boolean result1 = coll.remove("hello");
        System.out.println(result1); // true
        System.out.println(coll); //[world,heima,java]

        //void clear();   清除集合所有的元素
        coll.clear();
        System.out.println(coll); //true/false

		//boolean contains(E e);  判断集合中是否包含某个元素
        boolean result2 = coll.contains("java");
        System.out.println("是否包含此元素?" + result2); //true/false

		//boolean isEmpty();  判断那个集合是否为空
        boolean result3 = coll.isEmpty();
        System.out.println("是否为空?"+result3); //true/false

        //int size();     获取集合的长度
        System.out.println("集合长度:"+coll.size());//集合长度:数字

		//Object[] toArray();     将集合转换成一个数组
        Object[] arr = coll.toArray();
        //有了这个数组之后就可以进行遍历数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]); //打印格式如:hello<br>world<br>heima<br>java<br>
        }
    }
}

二、Iterator迭代器

Iterator接口
* java.util.Iterator接口:迭代器(对集合进行遍历)
* 有两个常用的方法:
    boolean hasNext();
       如果仍有元素可以迭代,则返回 true。
       判断集合中还有没有下一个元素,有就返回true,没有就返回false
    E next();
       返回迭代的下一元素
       取出集合中的下一元素
* Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊。
* Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象。
        Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。
* 迭代器的使用步骤(重点):
    1. 使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
    2. 使用Iterator接口中的方法nasNext判断还有没有下一元素
    3. 使用Iterator接口中的方法next取出集合中的下一元素

package com.itheima.demo07;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo01Iterator {
    public static void main(String[] args) {
        //创建一个集合
        Collection<String> coll = new ArrayList<>();
        //往集合中添加数组
        coll.add("姚明");
        coll.add("科比");
        coll.add("麦迪");
        coll.add("詹姆斯");
        coll.add("艾弗森");

        /*
        1. 使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
        注意:
            Iterator<E> 接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型。
         */
        //多态:       接口  =  实现类对象
        Iterator<String> it = coll.iterator();

          /*
	        发现使用迭代器取出集合中元素的代码,是一个重复的过程
	        所以我们可以使用循环优化
	        不知道集合中有多少元素,使用while循环
	        循环结束的条件,hasNext方法返回false
         */
        while (it.hasNext()) { //while循环实现迭代器
            String e = it.next();
            System.out.println(e); //[集合中的数据]
        }
        System.out.println("====================");

        for (Iterator<String> it2 = coll.iterator(); it2.hasNext(); ) { //for循环实现迭代器
            String e = it2.next();
            System.out.println(e);
        }

/*
// 2. 使用Iterator接口中的方法hasNext判断还有没有下一元素
        boolean b = it.hasNext();
        System.out.println(b);  //true/false

// 3. 使用Iterator接口中的方法next取出集合中的下一元素
        String s = it.next();
        System.out.println(s); //姚明

        b = it.hasNext();
        System.out.println(b);  //true
        s = it.next();
        System.out.println(s); //科比

        b = it.hasNext();
        System.out.println(b);  //true
        s = it.next();
        System.out.println(s); //麦迪

        b = it.hasNext();
        System.out.println(b);  //true
        s = it.next();
        System.out.println(s); //詹姆斯

        b = it.hasNext();
        System.out.println(b);  //true
        s = it.next();
        System.out.println(s); //艾弗森

        b = it.hasNext();
        System.out.println(b);  //没有元素,返回false
        s = it.next();
        System.out.println(s); //没有元素,再取出元素,会抛出异常: NoSuchElementException

*/
    }
}

在这里插入图片描述

三、增强for循环

* 增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
    是JDK1.5之后出现的新特性
    Collection<E>extends Iterable<E>: 所有的单列集合都可以使用增强for
    public interface Iterable<T> 实现这个接口允许对象成为 “foreach” 语句的目标。

* 增强for循环:用来遍历集合和数组

    格式:
        for(集合/数组的数据类型 变量名:集合名/数组名){
            sort(变量名);
        }
package com.itheima.demo07;

import java.util.ArrayList;
import java.util.Arrays;

public class Demo02Foreach {
    public static void main(String[] args){
        demo01();
    }

    //使用增强for循环遍历集合
    private static void demo02(){
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        for(String s : list){
            System.out.println(s);
        }
    }

    //使用增强for循环遍历数组
    private static void demo01() {
        int[] arr = {1,2,3,4,5};
        for (int i:arr) {
            System.out.println(i);
        }
    }
}

四、泛型

泛型详解

为什么要使用泛型
把运行时异常提前到编译时异常
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?

顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),

然后在使用/调用时传入具体的类型(类型实参)。

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,

操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
				
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);

for(int i = 0; i< arrayList.size();i++){
    String item = (String)arrayList.get(i);
    Log.d("泛型测试","item = " + item);
}

毫无疑问,上述程序的运行结果将会以崩溃的方式结束:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
ArrayList可以存放任意类型,例子中添加了一个String类型,添加了一个Integer类型,再使用时都以String的方式使用,因此程序崩溃了。为了解决类似这样的问题(在编译阶段就可以解决),泛型应运而生。

我们将第一行声明初始化list的代码更改一下,编译器会在编译阶段就能够帮我们发现类似这样的问题。
List<String> arrayList = new ArrayList<String>();
...
//arrayList.add(100); 在编译阶段,编译器就会报错
* 泛型的特性
	泛型只在编译阶段有效。看下面的代码:
List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    Log.d("泛型测试","类型相同");
}
输出结果:D/泛型测试: 类型相同。
通过上面的例子可以证明,在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型
使用泛型的好处与弊端
* 创建集合对象,使用泛型:
    好处:
      1. 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
      2. 把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
    弊端:
      泛型是什么类型,只能存储什么类型的数据

* 创建集合对象,不使用泛型:
     好处:
         集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据
     弊端:
         不安全,会引发异常
package com.itheima.demo07;

import java.util.ArrayList;
import java.util.Iterator;

public class demo03Generic {
    public static void main(String[] args) {
        show01();
    }

	// 创建集合对象,使用泛型
    private static void show02() {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
//        list.add(1);//编译期报错,add(java.lang.String)in ArrayList cannot be applied to (int)
        //使用迭代器遍历List集合
        Iterator<String> it = list.iterator();
        while (it.hasNext()) ;
        String s = it.next();
        System.out.println(s + "->"+s.length());
    }

    /*
     创建集合对象,不使用泛型
     */

    private static void show01() {
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add(1);

        //使用迭代器遍历List集合
        //获取迭代器
        Iterator it = list.iterator();
        //使用迭代器中的方法 hasNext和 next遍历集合
        while (it.hasNext()) {
            //取出元素也是Object类型
            Object obj = it.next();
            System.out.println(obj);

            //想要使用String类特有的方法,length获取字符串的长度
            //需要向下转型
            //会抛出异常:ClassCastException: java.lang.Integer cannot be cast to java.lang.String
            String s = (String) obj;
            System.out.println(s.length());
        }
    }
}
含有泛型的类
* 当把类实例化为对象,即new 一个对象的时候,泛型就有了具体的类型
* 定义一个含有泛型的类,模拟ArrayList集合
	泛型是一个位置的数据类型,当我们不确定使用什么数据类型的时候,可以使用泛型
	泛型可以接收任意的数据类型,可以使用Integer,String,Student...
    创建对象的时候可以确定泛型的数据类型

package com.itheima.demo07;

public class GenericClass<E> {  //参数类型由 String改为 E
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}
package com.itheima.demo07;

import java.util.Objects;

public class Demo02GenericClass {
    public static void main(String[] args){
        //不写泛型默认为Object类型
        GenericClass gc = new GenericClass(); //gc为Object类型-GenericClass类型
        gc.setName("只能是字符串");
        Object obj = gc.getName();
        System.out.println(name); //只能是字符串

        //创建GenericClass对象,泛型使用Integer类型,(创建对象的时候,确定泛型类型)
        GenericClass<Integer> gc2 = new GenericClass<>();
        gc2.setName(1);

        Integer name = gc2.getName();
        System.out.println(name);

        //创建GenericClass对象,泛型使用String类型
        GenericClass<String> gc3 = new GenericClass<>();
        gc3.setName("小明");
        String name1 = gc3.getName();
        System.out.println(name1);
    }
}
含有泛型的方法
* 定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间

* 格式:
    修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
          方法体;
    }

	含有泛型的方法,在调用方法的时候确定泛型的数据类型
	传递什么类型的参数,泛型就是什么类型

package com.itheima.demo07;

public class GenericMethod {
    //定义一个含有泛型的方法
    public <M> void  method01(M m){
        System.out.println(m);
    }

    //定义一个含有泛型的静态方法
    public static <S> void method02(S s){
        System.out.println(s);
    }
}
package com.itheima.demo07;

/*
测试含有泛型的方法
 */
public class Demo03GenericMethod {
    public static void main(String[] args) {
        //首先创建爱你GenericMethod对象
        GenericMethod gm = new GenericMethod();


        /*
        调用含有泛型的方法method
        传递什么类型,泛型就是什么类型
         */
        gm.method01(10);
        gm.method01("abc");
        gm.method01(8.8);
        gm.method01(true);

        gm.method02("静态方法,不建议创建对象使用");

        //静态方法,通过类名,方法名(参数)可以直接使用
        GenericMethod.method02("静态方法");
        GenericMethod.method02(1);
    }
}
含有泛型的接口
接口使用什么泛型,实现类就使用什么泛型,类跟着接口走。
package com.itheima.demo07;

/*
定义含有泛型的接口
 */
public interface GenericInterface<I> {
    public abstract void method(I i);
}
package com.itheima.demo07;

/*
含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
public interface list<E>{
    boolean add(E e);
    E get(int index);
}
public class ArrayList<E> implement List<E>{
    public boolean add(E e) {}
    public E get(int index) {}
}

 */
public class GenericInterfaceImpl2<I> implements GenericInterface<I>{
    @Override
    public void method(I i) {
        System.out.println(i);
    }
}
package com.itheima.demo07;

/*
测试含有泛型的接口
 */
public class Demo04GenericInterface {
    public static void main(String[] args){
        //创建GenericInterfaceImpl对象
        GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
        gi1.method("字符串"); //Object类型

        //创建GenericInterfaceImpl2对象
        GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>(); //Integer类型
        gi2.method(10);

        GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
        gi3.method(8.8);
    }
}
泛型的通配符
* 泛型的通配符:
    ?:代表任意的数据类型
* 使用方式:
    不能创建对象使用
    只能作为方法的参数使用
package com.itheima.demo07;

import java.util.ArrayList;
import java.util.Iterator;

public class Demo05Generic {
    public static void main(String[] args) {
        ArrayList<Integer> list01 = new ArrayList<>(); //数组集合对象
        list01.add(1);
        list01.add(2);

        ArrayList<String> list02 = new ArrayList<>();
        list02.add("a");
        list02.add("b");

        printArray(list01); //1   2
        printArray(list02); //a   b

//        ArrayList<?> list03 = new ArrayList<?>(); //定义的时候不能用泛型的通配符

    }

    /*
        定义一个方法,能遍历所有类型的ArrayList集合
        这时候我们不知道ArrayList集合使用什么数据类型,可以使用泛型的通配符?来接收数据类型
        注意:
            泛型没有继承的概念

     */

    public static void printArray(ArrayList<?> list){
        //使用迭代器遍历集合
        Iterator<?> it = list.iterator();
        while (it.hasNext()){
            //it.next()方法,取出的元素是Object,可以接收任意的数据类型
            Object o = it.next();
            System.out.println(o);
        }

    }
}

斗地主综合案例

在这里插入图片描述

package com.itheima.demo08;

/*
    斗地主综合案例:
    1. 准备牌
    2. 洗牌
    3. 发牌
    4. 看牌
 */

import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;

public class DouDiZhu {
    public static void main(String[] args) {
        //1. 准备牌
        // 定义一个存储54张牌的ArrayList集合,泛型使用String
        ArrayList<String> poker = new ArrayList<>();
        //定义两个数组,一个数组存储牌的花色,一个数组存储牌的序号
        String[] colors = {"♠", "♥", "♣", "♦"};
        String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
        //先把大王和小王存储到poker集合中
        poker.add("大王");
        poker.add("小王");
        //循环嵌套遍历两个数组,组装52张牌
        for (String number : numbers) {
            for (String color : colors) {
                //System.out.println(color+number);
                //把组装好的牌存储到poker集合中
                poker.add(color+number);
            }
        }
        System.out.println(poker);

        /*
        2. 洗牌
        使用集合的工具类Collections中的方法
        static void shuffle(List<?> list) 使用默认随机源对指定列表进行置换
         */
        Collections.shuffle(poker);
        //System.out.println(poker);    //每次输出结果都不一样,可用此方法进行洗牌

        /*
            3. 发牌
         */
        //定义4个集合,存储玩家的牌和底牌
        ArrayList<String> player01 = new ArrayList<>();
        ArrayList<String> player02 = new ArrayList<>();
        ArrayList<String> player03 = new ArrayList<>();
        ArrayList<String> diPai = new ArrayList<>();

        /*遍历poker集合,获取每一个集合
        使用poker集合的索引%3 给3个玩家轮流发牌
        剩余3张牌给底牌
        注意:
            先判断底牌(i >= 51),否则牌就发没了
         */
        for(int i = 0; i < poker.size(); i++){
            //获取每一张牌
            String p = poker.get(i);
            //轮流发牌
            if(i >= 51){
                //改底牌发牌
                diPai.add(p);
            }else if(i % 3 == 0){
                //给玩家1发牌
                player01.add(p);
            }else if(i % 3 == 1){
                //给玩家2发牌
                player02.add(p);
            }else if(i % 3 == 2){
                //给玩家3发牌
                player03.add(p);
            }
        }
        //看牌
        System.out.println("刘德华:" + player01);
        System.out.println("周润发:" + player02);
        System.out.println("周星驰:" + player03);
        System.out.println("底牌:" + diPai);
    }
}
标题“51单片机通过MPU6050-DMP获取姿态角例程”解析 “51单片机通过MPU6050-DMP获取姿态角例程”是一个基于51系列单片机(一种常见的8位微控制器)的程序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计和三轴陀螺仪的六自由度传感器,广泛应用于运动控制和姿态检测领域。该例程利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计和陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字符形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机和MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编程简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性和角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编程语言的源代码、配置文件、用户手册、示例程序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线和控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式和数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务程序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
MathorCup高校数学建模挑战赛是一项旨在提升学生数学应用、创新和团队协作能力的年度竞赛。参赛团队需在规定时间内解决实际问题,运用数学建模方法进行分析并提出解决方案。2021年第十一届比赛的D题就是一个典型例子。 MATLAB是解决这类问题的常用工具。它是一款强大的数值计算和编程软件,广泛应用于数学建模、数据分析和科学计算。MATLAB拥有丰富的函数库,涵盖线性代数、统计分析、优化算法、信号处理等多种数学操作,方便参赛者构建模型和实现算法。 在提供的文件列表中,有几个关键文件: d题论文(1).docx:这可能是参赛队伍对D题的解答报告,详细记录了他们对问题的理解、建模过程、求解方法和结果分析。 D_1.m、ratio.m、importfile.m、Untitled.m、changf.m、pailiezuhe.m、huitu.m:这些是MATLAB源代码文件,每个文件可能对应一个特定的计算步骤或功能。例如: D_1.m 可能是主要的建模代码; ratio.m 可能用于计算某种比例或比率; importfile.m 可能用于导入数据; Untitled.m 可能是未命名的脚本,包含临时或测试代码; changf.m 可能涉及函数变换; pailiezuhe.m 可能与矩阵的排列组合相关; huitu.m 可能用于绘制回路图或流程图。 matlab111.mat:这是一个MATLAB数据文件,存储了变量或矩阵等数据,可能用于后续计算或分析。 D-date.mat:这个文件可能包含与D题相关的特定日期数据,或是模拟过程中用到的时间序列数据。 从这些文件可以推测,参赛队伍可能利用MATLAB完成了数据预处理、模型构建、数值模拟和结果可视化等一系列工作。然而,具体的建模细节和解决方案需要查看解压后的文件内容才能深入了解。 在数学建模过程中,团队需深入理解问题本质,选择合适的数学模
以下是关于三种绘制云图或等高线图算法的介绍: 一、点距离反比插值算法 该算法的核心思想是基于已知数据点的值,计算未知点的值。它认为未知点的值与周围已知点的值相关,且这种关系与距离呈反比。即距离未知点越近的已知点,对未知点值的影响越大。具体来说,先确定未知点周围若干个已知数据点,计算这些已知点到未知点的距离,然后根据距离的倒数对已知点的值进行加权求和,最终得到未知点的值。这种方法简单直观,适用于数据点分布相对均匀的情况,能较好地反映数据在空间上的变化趋势。 二、双线性插值算法 这种算法主要用于处理二维数据的插值问题。它首先将数据点所在的区域划分为一个个小的矩形单元。当需要计算某个未知点的值时,先找到该点所在的矩形单元,然后利用矩形单元四个顶点的已知值进行插值计算。具体过程是先在矩形单元的一对对边上分别进行线性插值,得到两个中间值,再对这两个中间值进行线性插值,最终得到未知点的值。双线性插值能够较为平滑地过渡数据值,特别适合处理图像缩放、地理数据等二维场景中的插值问题,能有效避免插值结果出现明显的突变。 三、面距离反比 + 双线性插值算法 这是一种结合了面距离反比和双线性插值两种方法的算法。它既考虑了数据点所在平面区域对未知点值的影响,又利用了双线性插值的平滑特性。在计算未知点的值时,先根据面距离反比的思想,确定与未知点所在平面区域相关的已知数据点集合,这些点对该平面区域的值有较大影响。然后在这些已知点构成的区域内,采用双线性插值的方法进行进一步的插值计算。这种方法综合了两种算法的优点,既能够较好地反映数据在空间上的整体分布情况,又能保证插值结果的平滑性,适用于对插值精度和数据平滑性要求较高的复杂场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值