Phase2 DAY4 List&泛形

总结

Collection
  |-- List
    |-- ArrayList
    |-- Vector
      |-- Stack
    |-- LinkedList
  |-- Queue
     |-- Deque
       |-- LinkedList

LinkedList

LinkedList 实现了接口 List, Deque

  • 底层是链表, 增删快, 查找慢
  • 不同步, 线程不安全, 效率高
构造方法

LinkedList() 
          构造一个空列表。 
LinkedList(Collection<? extends E> c) 
          构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。 
/
LinkedList 特有的API

public void addFirst(E e)addLast(E e)
public E getFirst()getLast() 
public E removeFirst()public E removeLast()
//
Deque接口实现的方法

     第一个元素(头部)                  最后一个元素(尾部)
     抛出异常       特殊值         抛出异常        特殊值
插入 addFirst(e)   offerFirst(e)  addLast(e)   offerLast(e)
移除 removeFirst() pollFirst()    removeLast() pollLast()
检查 getFirst()    peekFirst()    getLast()    peekLast()

栈的API
void push(E e)
E pop()
E peek()
///
ListIterator<E> listIterator(int index) 
          返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始 
Iterator<E> descendingIterator() 
          返回以逆向顺序在此双端队列的元素上进行迭代的迭代器 
boolean removeFirstOccurrence(Object o) 
          从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。  
boolean removeLastOccurrence(Object o) 
          从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 
          

继承Vector的栈Stack

API:
    boolean empty()
    E peek()
    E pop()
    E push(E item)
    int search(Object o)

但是不推荐使用Vector的栈,而推荐使用Deque的栈,因为:

  • Stack继承Vector的, 效率比较低
  • Stack具有Vector所有的API, 可以在任意位置添加和删除, 使用起来不是很安全。

Vector的栈


问题:哪一端当作栈顶比较好?尾

MyStack持有了Vector对象,因此,它就可以具有Vector的所有功能,并且可以对这些功能进行"加强".

哪些技术可以对一个方法进行加强?
    a. 继承
    b. 组合
哪一种方式比较好?
    设计原则:组合优先于继承。
什么时候可以使用继承
    类与类之间是 is a 的关系的时候。
 
public class MyStack {
    private Vector vector; //组合

    public MyStack(Vector vector) {
        this.vector = vector;
    }

    public void push(Object obj){
        vector.add(obj);
    }

    public Object pop() {
        return vector.remove(vector.size() - 1);
    }

    public Object peek() {
        return vector.get(vector.size() - 1);
    }

    public boolean isEmpty() {
        return vector.isEmpty();
    }

}

去重练习

思路1:
    a. 新建一个List
    b. 遍历原集合,拿到每一个元素
        如果在新集合中已经存在, 不添加
        如果在新集合中不存在, 添加
        
public static List removeDuplicated(List list) {
        List result = new ArrayList();
        for(Iterator it = list.iterator(); it.hasNext(); ) {
            Object obj = it.next();
            if (!result.contains(obj)) {
                result.add(obj);
            }
        }
        return result;
 }


思路2:
    拿到第一个元素, 然后删除后面所有与第一个元素相等的元素
    拿到第二个元素, 然后删除后面所有与第二个元素相等的元素...

 public static void removeDuplicated(List list) {
        // int size = list.size();
        for(int i = 0; i < list.size(); i++) {
            Object obj = list.get(i);
            for (int j = i + 1; j < list.size(); j++) {
                if (obj.equals(list.get(j))) {
                    list.remove(j);
                    j--; // caution! 需要回退一步
                }
            }
        }
    }

泛形

概念
 有许多原因促成了泛型的出现,而最引人注目的一个原因,就是为了创造容器类。有些情况下,我们确实希望容器能够同时持有多种类型的对象。但是,通常而言我们只会使用容器来存储一种类型的对象。
 泛型的主要目的之一就是用来指定容器要持有什么类型的,因此与其使用Object,我们更喜欢暂时不指定类型,而是稍后再決定具体使用什么类型。要达到这个目的,需要使用类型参数,用尖括号括住,放在类名后面。然后在使用这个类的时候,再用实际的类型替换此类型参数。
 如果不申明泛型的类,JAVA则会自动使用Object来描述创建的对象,使用数据时必须进行强制类型转换,存在安全隐患。


泛型类
格式:public class 类名<泛型类型1,>
泛型的命名
    语法规则:只要满足标识符的规则即可
    业界规则:用大写的字母表示
        T   type
        E   element
        K   key
        V   value
        U

public class Tool<T> {// T就是泛型(类型形参), 泛型定义在类上, 作用域就是整个类
    T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}



泛型接口
格式:public  interface 接口名<泛型类型1>
泛型接口的实现类
    a. 泛型类
    b. 普通类
    
public interface Auto<T> { //泛型定义在接口上面, 作用域就是整个接口
    T run(T t);
}


泛形方法

public static<T> void fun(Messages temp){
        System.out.println(temp.getMsg());
    }
    


泛型的好处:
    a. 提高了程序的安全性
    b. 将运行期遇到的问题转移到了编译期
    c. 省去了类型强转的麻烦

设计原则:尽早失败原则
    a.节省计算资源
    b.容易定位问题

public class GenericDemo1 {
    public static void main(String[] args) {
       
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        dosomething(list);
    }

    private static void dosomething(List list) {
        for(Iterator it = list.iterator(); it.hasNext(); ) {
            String s = (String) it.next(); // ClassCastException
            System.out.println(s.toUpperCase());
        }
    }//不使用泛形需强制转换

    private static void dosomething(List<String> list) {
        for(Iterator<String> it = list.iterator(); it.hasNext(); ) {
            String s = it.next();
            System.out.println(s.toUpperCase());
        }
    }
}



问题:
    String是Object的子类吗? 是
    String[]是Object[]的子类吗? 不是
	为了代码书写方便, JVM对数组类型进行了特殊处理。 但是同时也引入了一些问题。
	数组是一个可协变类型。
	集合不是一个可协变类型。
public static void main(String[] args) {
        String s = "hello";
        Object obj = s;
        String[] strs = new String[10];
        Object[] objs = strs;
        Date[] dates = strs;//error
        objs[1] = new Object(); // ArrayStoreException*/

        List<String> strs = new ArrayList<>();
        List<Object> objs = strs;//error
    }




泛型通配符
 利用泛型技术虽然解决了向下转型所带来的安全隐患,但同时又会产生一个新的问题:即便是同一个类,由于泛形设置类型不同,其对象表示的含义也不一样,因此不能直接进行引用操作.

例如
public static void fun(Messages<String> temp){
	此方法只能用来接收String类型的对象
        System.out.println(temp.getMsg());
}

public static void fun(Messages<?> temp){
	此方法可以接受任意类型的的对象
        System.out.println(temp.getMsg());
}


class Messages<T>{
    private T msg;

    public T getMsg() {
        return msg;
    }

    public void setMsg(T msg) {
        this.msg = msg;
    }
}

一个问题:能否使用Object描述一切泛型,或者不设置类型?

  • 问题的关键是:在明确设置一个类为泛型类型时若没有继承的概念范畴,也就是说虽然Object类与String类属于父子关系,但在泛型中就是两个完全独立的概念
  • 如果在定义时不设置类型,也可以实现任意泛型类对象的就收,但存在一个问题:不指派类型,JAVA则默认Object,也就是说方法中可以随意修改接收到的对象的属性内容,例如:
	public static void main(String[] args) {
        Messages<Integer> m1 = new Messages<>();
        m1.setMsg(100);
        fun(m1);
    }
    public static void fun(Messages temp){
        temp.setMsg("我把你Integer改成String了牛不牛皮");
        System.out.println(temp.getMsg());
    }
    此时输出的就是String类,Integer被改了属性
  • 上述方法就是非常不严谨的,所以必须要使用通配符<?>来制约这种随意修改数据的问题,故被通配符修饰的类型只可表示取出,不能设置内容,否则编译器报错.

设置泛型上下限

  • ? extends E
    设置上限,E及其子类

  • ? super E
    设置下限,E及其父类


泛型通配符:提供类似数组的功能,但是同时要避免数组可能存在的问题。

        Collection<Object> c1 = new ArrayList<Object>();//error
        Collection<Object> c2 = new ArrayList<Animal>();//error
        Collection<Object> c3 = new ArrayList<Dog>();//error
        Collection<Object> c4 = new ArrayList<Cat>();//error

        Collection<?> c1 = new ArrayList<Object>();
        Collection<?> c2 = new ArrayList<Animal>();
        Collection<?> c3 = new ArrayList<Dog>();
        Collection<?> c4 = new ArrayList<Cat>();
        c2.add("string");//error

        Collection<? extends Animal> c1 = new ArrayList<Object>();//error
        Collection<? extends Animal> c2 = new ArrayList<Animal>();
        Collection<? extends Animal> c3 = new ArrayList<Dog>();
        Collection<? extends Animal> c4 = new ArrayList<Cat>();
        c3.add(new Animal());//error
        c3.add(new Dog());//error
        c3.add(new Cat());//error

        Collection<? super Animal> c1 = new ArrayList<Object>();
        Collection<? super Animal> c2 = new ArrayList<Animal>();
        Collection<? super Animal> c3 = new ArrayList<Dog>();//error
        Collection<? super Animal> c4 = new ArrayList<Cat>();//error
        c2.add(new Animal());
        c2.add(new Object());//error

练习:往List类型的对象中,插入一个整数。
   如何解决这个问题?我们可以利用反射绕过泛型检查

        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        // list.add(1);//error

        Class<? extends List> cl = list.getClass();
        Method addMethod = cl.getDeclaredMethod("add", Object.class);
        addMethod.invoke(list, 1);
        System.out.println(list);

       /* String s = list.get(3);
        System.out.println(s);*/无法获取

        如何获取这个值呢?继续通过反射
        Method getMethod = cl.getDeclaredMethod("get", int.class);
        int value = (int) getMethod.invoke(list, 3);
        System.out.println(value);

数组和集合的转换

        List<String> list = new ArrayList<>();
        list.add("刘亦菲");
        list.add("茜茜");
        list.add("赵灵儿");

        String[] arr = new String[3];
        String[] strs = list.toArray(arr);
        System.out.println(Arrays.toString(strs));//[刘亦菲, 茜茜, 赵灵儿]
        System.out.println(strs == arr); // true*/

        String[] arr = new String[1];
        String[] strs = list.toArray(arr);
        System.out.println(Arrays.toString(strs));//[刘亦菲, 茜茜, 赵灵儿]
        System.out.println(Arrays.toString(arr));//[null]
        System.out.println(strs == arr);//false

        String[] arr = new String[list.size()];
        list.toArray(arr);
        System.out.println(Arrays.toString(arr));[刘亦菲, 茜茜, 赵灵儿]

增强形循环:foreach


foreach循环:
作用:简化数组和Collection集合的遍历
格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
	使用变量即可,该变量就是元素
}

好处:简化了数组和集合的遍历操作
坏处:
    a. 不能获取索引信息
    b. 不能修改集合和数组
    
建议:
    尽量使用foreach循环, 简洁易懂。
    
原理:
    编译器对数组单独进行处理
    集合的foreach循环底层就是迭代器

问题:什么情况下可以使用foreach循环呢?
    数组, 集合
    实现了Iterable接口的对象, 都可以使用foreach循环

Iterable: (JDK1.5)
    实现这个接口允许对象成为 "foreach" 语句的目标。
    API:
        Iterator<T> iterator()
        
// 遍历数组

一般方法:
        int[] arr = {1, 2, 3};
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        
foreach方法:
        for(int a : arr) {
            System.out.print(a + " ");
        }
        System.out.println();

 // 遍历集合

        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        
一般方法:
        for(Iterator<String> it = list.iterator(); it.hasNext(); ) {
            String s = it.next();
            System.out.print(s + " ");
        }
        System.out.println();
        
foreach方法:
        for(String s : list) {
            System.out.print(s + " ");
            // if ("hello".equals(s)) list.remove(s);//reeor
        }
        System.out.println();
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的文件内容,本文将详细解析“飞行弹道仿真”的核心知识点,主要涉及MATLAB编程环境下的弹道仿真实现过程。 ### 弹道仿真概述 弹道仿真是一种通过数学模型来预测导弹、炮弹等飞行器在空中飞行轨迹的技术。在军事、航天等多个领域都有着广泛的应用。对于弹道仿真的研究不仅有助于提升武器系统的精确度,还能帮助科研人员更好地理解空气动力学原理以及飞行器的动力特性。 ### MATLAB环境下弹道仿真的实现 #### 1. **初始化参数** 在代码中,作者首先对一系列变量进行了初始化处理。这些变量包括但不限于:质量(`m`), 速度(`V`), 高度(`H`)等关键物理量。此外,还定义了一些常量如重力加速度(`g`)、空气密度(`rho_air`)等。 #### 2. **地面高度分布设定** 通过设定地面高度随距离变化的函数(`x_d` 表示水平距离,`H_d` 表示对应的高度),可以模拟不同的地形特征。这里使用了一个分段函数来表示地面高度的变化情况。 #### 3. **动态方程与运动方程** - **动态方程**:描述了导弹受到的外力作用(推力、阻力、升力)以及重力对其运动状态的影响。 - 推力(`P`)、阻力(`X`)、升力(`Y`)等参数被用于计算导弹的速度和角度变化。 - 通过积分运算更新速度、角度等状态量。 - **运动方程**:描述了导弹在三维空间中的位置变化情况。 - 包括水平方向速度(`equ4_Kinematic_x`)、垂直方向速度(`equ5_Kinematic_y`)以及姿态角(`equ6_Kinematic_Theta`)的变化。 - 这些方程同样通过积分方法进行求解。 #### 4. **控制律设计** 控制律设计是确保导弹按照预定轨迹飞行的关键环节。例如,代码中采用了简单的PID控制策略来调整导弹的姿态角。具体地: - `k_phi` 和 `k_phidiff` 分别代表比例系数和微分系数。 - 通过调整这些系数的值,可以优化导弹的飞行性能,使其更加稳定且能够准确跟踪目标。 #### 5. **数值积分方法** 为了求解动态方程与运动方程,文中采用了一种数值积分方法(`integral_to_next`)。该方法可以近似计算出导弹在下一时刻的状态量(速度、角度等)。虽然具体的实现细节没有给出,但通常这类方法基于欧拉法或者更高级的龙格-库塔法等。 ### 结论 本文通过对“飞行弹道仿真”这一主题的深入探讨,不仅详细介绍了如何使用MATLAB进行弹道仿真,而且还重点讲解了其中涉及到的重要概念和技术细节,如地面高度分布设定、动态方程与运动方程、控制律设计以及数值积分方法等。对于希望深入了解弹道仿真技术的研究者来说,本文提供了丰富的参考资料和实施指南。通过这样的仿真研究,不仅可以提高导弹等飞行器的设计精度,还能为未来航空航天技术的发展提供强有力的支持。
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值