GVKun编程网logo

5.6(java学习笔记) queue(java queue deque)

21

在这篇文章中,我们将为您详细介绍5.6的内容,并且讨论关于java学习笔记queue的相关问题。此外,我们还会涉及一些关于1.10(java学习笔记)super关键字、1.11(java学习笔记)封装

在这篇文章中,我们将为您详细介绍5.6的内容,并且讨论关于java学习笔记 queue的相关问题。此外,我们还会涉及一些关于1.10(java学习笔记)super关键字、1.11(java学习笔记)封装、1.14(java学习笔记)数组、1.1(java 学习笔记) 面向过程与面向对象的知识,以帮助您更全面地了解这个主题。

本文目录一览:

5.6(java学习笔记) queue(java queue deque)

5.6(java学习笔记) queue(java queue deque)

一.queue接口

queue的中文意思是队列,是一种以先进先出方式处理数据的集合。

 

队列还提供额外的插入、提取和检查操作。这些方法都以两种形式存在:一种在操作失败时抛出异常,另一种返回特殊值(根据操作,为空或为假)。

后一种形式的插入操作是专门针对容量受限的队列实现设计的

 

有些方法以两种形式存在,只是操作失败时处理的方式不同,一个是抛出异常,一个是返回特殊值(false或null)。

这个根据自己需要进行选择。

 

实现这个接口的类有:

 

下面说两个常用方法。

1.boolean offer(E e)

向队列中插入元素,如果操作成功返回true,反之返回false。

 

2.E poll()

检索并移除队列的头部,返回移除的队列头部元素,如果头部为空则返回null。

 

我们来举个例子:

import java.util.ArrayDeque;
import java.util.Queue;

public class Demo01 {
    public static void main(String[] args) {
        Queue<Request> que = new ArrayDeque<Request>();//ArrayDeque是支持容量扩展的。
        for(int i = 0; i < 10; i++){
            final int num = i;
            que.offer(new Request(){//在队列中放入10个元素,此处使用匿名内部类
                @Override
                public void deposit() {
                    // TODO Auto-generated method stub
                    System.out.println("第"+num+"个人存款:" + Math.random()*10000);//生产随机出模拟存款
                }
            });
        }
        dealWith(que);//输出队列。
        System.out.println("--------");
        dealWith(que);
    }
    public static void dealWith(Queue<Request> que){//输出队列的方法
        Request req = null;
        while((req = que.poll()) != null){
            req.deposit();
        }
    }
}

interface Request{//定义的一个接口
    void deposit();
}
运行结果:
第0个人存款:8619.233801715016
第1个人存款:5111.3672776256135
第2个人存款:3833.7846958074883
第3个人存款:534.977625279095
第4个人存款:40.69671570731348
第5个人存款:986.8179704462143
第6个人存款:5995.7651112520325
第7个人存款:8142.90423161368
第8个人存款:5153.935940310687
第9个人存款:4599.385486329686
--------

可以看到,poll是移除队列头部并返回,所以输出完后无法再次输出队列。

 

其实添加元素就是不停在队列尾部添加,移除时不停将头部置为null并将头部后移。

我们来看下源码:

用于存放数据的是一个object类型的数组。

初始长度为16,容量不足可自动扩容。

 

offer(E e)

offer()最后调用的是addLast,tail是尾部的索引,我们可以看到将元素添加到尾部后,

尾部索引后移一位。

 

我们接着来看下poll();

移除元素就将头部元素给result,然后判断下如果头部为空则返回null.

后面将头部置null,然后返回头部元素,头部索引后移一位。

 

我们可以发现在队列中有向头部添加元素的方法,也有像尾部添加元素的方法。

这些结合下,我们能否用队列实现堆栈的功能?

 

堆栈是先进后出,我们也看了上列代码中添加时是在尾部添加,最后获取时是在头部获取才造成了先进先出的现象。

假如我们不断在尾部添加,添加完后再不断从尾部获取这样是不是就是实现了后进先出。

还是上列代码,我们只需要修改一个地方就可以了,将从头部开始移除并返回移除元素,改成从尾部开始移除,并返回尾部元素即可。

 

import java.util.ArrayDeque;
import java.util.Queue;

public class Demo01 {
    public static void main(String[] args) {
        Queue<Request> que = new ArrayDeque<Request>();for(int i = 0; i < 10; i++){
            final int num = i;
            que.offer(new Request(){
                @Override
                public void deposit() {
                    // TODO Auto-generated method stub
                    System.out.println("第"+num+"个人存款:" + Math.random()*10000);
                }
            });
        }
        dealWith(que);
        System.out.println("--------" + o.length);
        dealWith(que);
    }
    public static void dealWith(Queue<Request> que){
        Request req = null;
        while((req = ((ArrayDeque<Request>) que).pollLast()) != null){//将poll中原先调用pollFirst改为pollLast.
            req.deposit();
        }
    }
}

interface Request{
    void deposit();
}
运行结果:
第9个人存款:4418.752779875663 第8个人存款:894.3762449014581 第7个人存款:6559.006752015596 第6个人存款:2725.551000497387 第5个人存款:1180.896859117061 第4个人存款:7267.814454629828 第3个人存款:9021.26681251365 第2个人存款:5066.769610999404 第1个人存款:6173.24968987338 第0个人存款:6288.854161224456 --------
//从后向前移除就是将尾部元素返回,并且将尾部前移一位。

1.10(java学习笔记)super关键字

1.10(java学习笔记)super关键字

supe主要是调用父类中被重写的方法及属性。

用下列代码那说明:

 

package cn.hcf.TestSuper;

public class TestSuper {
    public static void main(String[] args){
        Student stu = new Student();
        stu.task();
    }
}

class Person{
    int ID;
    void task(){
        ID = 100;
        System.out.println("工作");
    }
}

class Student extends Person{
    int ID;
    void task(){            //task方法已被子类重写
        ID = 200;
        super.task();       //通过super调用父类中的task方法,应打印“工作”。
        System.out.println("学习");
        System.out.println("Person:" + super.ID + "\n" + "Student:" + ID);  //super是父类中ID的值应为100
    }    
}

 

运行结果:
工作
学习
Person:100
Student:200

 

还有一个知识点就是,所有类的第一句都隐含一个super(),写于不写(不写编译器会自动加上)都是这句话。;意思是调用父类的无参构造方法。

用下面代码说明:

 

 1 package cn.hcf.TestSuper;
 2 
 3 public class TestSuper {
 4     public static void main(String[] args){
 5         Student stu = new Student();
 6         
 7     }
 8 }
 9 
10 class Person{
11     public Person(){
//super(); 隐含的
12 System.out.println("Person"); 13 } 14 } 15 16 class Student extends Person{
//super(); 隐含的
17 public Student(){ 18 System.out.println("Student"); 19 } 20 }
运行结果:
Person
Student

我们会发现,我们只创建了一个Studetn类的对象,应该只调用Student的无参构造方法,可是最后它也调用了Person的无参构造方法。

这是因为每一个类的第一句都隐含了一句super();所以是层层向上追溯,直到Oject类。

所以以我们这代码为例,层层向上追溯,最先创建好的是Object,然后创建Person,person包裹object,再创建Student,student包裹person,这样层层包裹。

 

 

 

 

1.11(java学习笔记)封装

1.11(java学习笔记)封装

封装将内部细节封装起来,只暴露外部接口。

比如我们的电视就将复杂的内部线路用外壳封装起来,只留下外部按钮或遥控,用户只需要知道按钮或遥控的作用就可以,无需明白电视内部是如何工作。

而且封装也保障了安全性,用户只能去使用暴露在外部的接口,不能改变内部结构,保障了正常运行。

 

 

封装后,使用者不必知晓复杂的内部功能如何实现(这时设计者的事),只需要知道暴露在外部的接口的功能即可,

便于使用者调用,对内部进行周全的考虑是设计者的事。

封装后内部的属性无法访问,也保障了程序的安全性(避免了某些误操作导致不需要修改的值发生了变化)。

 

封装就是内部某些属性方法对外不可见(即不能进行修改),这时我们就需要通过访问控制符来实现封装。

 

 

通过设置访问权限就可以实现封装,

 

下面举一个例子

 

 1 public class Test {
 2     public static void main(String[] args){
 3         Person man = new Person();
 4         man.setAge(1000);   //年龄1000显然是不行的,如果没有封装可以直接访问age
 5         man.setNmae("hcf"); //显然会造成问题。
 6         man.putInformation();
 7     }
 8 }
 9 
10 class Person{                  //person相当于被封装起来了,只暴露要使用的部分,其他部分不可见、             
11     private int age;           //age和name只能被本类看见,别的类要想访问必须通过暴露在外的setAge和setNmae函数。
12     private String name;
13     void putInformation(){
14         System.out.println("姓名:" + name + "\n" + "age:" + age);
15     }
16     void setNmae(String name){
17         this.name = name;
18     }
19     void setAge(int age){   //可能大家会问为什么要这样”多此一举“,非要通过一个暴露在外的函数来实现访问。
20         if(age < 0 || age > 130){//大家看下面,通过一个函数来接受参数,可以对这个传递进来的数据进行判断,
21             System.out.println("请输出正确的年龄");//可以有效避免问题数据,不当访问等造成的重要参数被修改,从而导致程序崩溃。
22         }else{                                   //这样封装起来即可以保证内部数据的正确性,安全性,也方便外部调用,
23             this.age = age;                      //可以实现高内聚,低耦合。
24             }
25     }
26 }

 

       

运行结果:
请输出正确的年龄
姓名:hcf
age:0

 

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

1.14(java学习笔记)数组

1.14(java学习笔记)数组

假如我们需要用到1000个相同类型的数据,肯定不可能创建1000个变量,

这样既不方便,也不直观,也不便于我们使用。这时就需要用到数组。

 

一、数组的声明与使用

1 public class Array {
2     public static void main(String[] args) {
3         int a[] = null;  //数据类型  数组名 = null;声明一维数组
4         a = new int[10]; //数组名 = new 数据类型[长度];分配内存给数组。
5     }
6     
7 }

首先第一句,声明了数组a,此时栈内存中就分配了一块内存空间给a,此时将null给a代表不指向任何实例(此时a只在栈内存中进行了创建,但是它没有指向堆内存中任何对象实例,也没有指向堆内存),所以不能使用(引用)具体的实例数据。

第二句,用new在堆内存中创建了十个int类型的存储空间,然后把这个内存空间的地址给a。

此时堆内存中就可以存放10个int型的数据,栈内存中的a存放了堆内存的地址值。这时可以通过数组a引用堆内存的内容。

 

二、数组元素的表示方法

数组用下标区别元素,下标从0到n-1;

例如创建的a数组长度为10,即下标从0~ 9;

a[10] 并不存在,引用a[10]会出现错误,下标只能到a[9];

public class Array {
    public static void main(String[] args) {
        int a[] = null;  
        a = new int[10]; 
        for(int i = 0; i < 10; i++){ //其中i < 10可以写成 i<a.length,
            a[i] = i;                //数组循环赋值并打印
            System.out.println(a[i]);
        }
        System.out.println(a.length);  //数组名.length代表数组的长度,且会返回一个int值。
    }    
}

 

运行结果:
0 1 2 3 4 5 6 7 8 9
10

 

三、数组的静态初始化

上面给数组赋值是在数组创建完毕后,再给数组中元素赋值,属于动态初始化。

在数组元素创建时就直接赋值属于静态初始化。

数据类型 数组名[] = {初始值0,初始值1,初始值2,···,初始值 n};

虽然声明时没有指定数组长度,但由初始化时初始值的个数编译器会自动确定长度和初始值个数相同。

 1 public class Array {
 2     public static void main(String[] args) {
 3         int a[] = {0,1,2,3,4,5,6,7,8,9};  
 4         for(int i = 0; i < a.length; i++){
 5             a[i] = i;
 6             System.out.println(a[i]);
 7         }
 8         System.out.println(a.length);
 9     }    
10 }
运行结果:
0 1 2 3 4 5 6 7 8 9
10

 

三、二维数组

一维数组可以看做是具有1行n列的元素的集合。

而二维数组可以看做是具有m行n列的元素的集合。

声明方法和一维类似,不同的是需要确定行数和列数。

1 public class Array {
2     public static void main(String[] args) {
3         int a[][] = new int[3][4]; //代表创建了一个三行四列的数组。
4     }    
5 }

 

二维数组的引用

public class Array {
    public static void main(String[] args) {
        int a[][] = new int[3][4];
int num = 0;
for(int i = 0; i <a.length; i++){ for(int j = 0; j < a[i].length; j++){ a[i][j] = num++; System.out.print(a[i][j] + " " );//前面的下标代表行,后面代表列 } System.out.println(); } } }
运行结果:
0 1 2 3
4 5 6 7
8 9 10 11

 

上列的a.length可以看做组成二维数组的一维数组的个数(例如上面可以看做由三个一维数组组成了二维数组),a[i].length可以看做当前行中数组的个数。

由此推到n维,假设有n维数组A;则a.length代表n维数组中n-1维数组的个数,a[i].length代表n-1维数组中n-2维数组的个数......

 

二维数组中每一行的元素个数也不一定相等

例如

 1 public class Array {
 2     public static void main(String[] args) {
 3         int a[][] = {{1,},{1,2},{1,2,3}};
 4         int num = 0;
 5         for(int i = 0; i <a.length; i++){
 6             for(int j = 0; j < a[i].length; j++){
 7                     a[i][j] = num++;
 8                     System.out.print(a[i][j] + " " );//前面的下标代表行,后面代表列
 9                 }
10             System.out.println();
11         }    
12     }    
13 }
运行结果:
0 
1 2 
3 4 5

初始化时一共有三个一维数组,但每一行的元素个数不同,a[i].length代表当前行中元素的个数。

我们尝试输出a[0][2]会出现java.lang.ArrayIndexOutOfBoundsException,代表数组下标越界。

说明a[0][2]没有分配内存,也可以说它不存在。

 

四、数组的引用传递

我们看下列代码

 1 public class Array {
 2     public static void main(String[] args) {
 3         int a[] = {1,2,3};
 4         fun(a);
 5         System.out.println(a[0]);
 6     }
 7     static void fun(int x[]){
 8         x[0] = 123;
 9     }
10 }
运行结果:
123

可以发现,我们将数组名a作为参数传递给了fun方法。

fun方法中修改了第一个元素的值,在main中输出的值也改变了了。

说明堆内存中的值被更改了。

 

传递过程:

首先前面讲到数组名存放的只是堆内存中创建好的数组空间的地址。

将数组名传递给函数fun传递的是堆内存空间的地址。

这时fun中的数组x[]就和main中的数组a[]指向了同一块地址。

利用x[]就可以对堆内存中内容进行操作。

fun方法结束后,数组x[]会被释放掉,但对堆内存的操作却保留了下来。

这点和c语言的指针类似。

 

五、java对数组的新特性(jdk1.5(javase5.0)之后)。

1.可变参数

在调用一个方法时,会根据定义的传递指定的参数。

而可变参数代表传递给方法的参数个数是不定的。

 

方法名称(类型...参数名称){

}

 

public class Array {
    public static void main(String[] args) {
        int a[] = new int[5];
            fun();
            fun(1);
            fun(1,2,3);
            fun(1,2,3,4,5);
    }
    
    private static void fun(int...arg){
          int i = 0;
          for(i = 0; i <arg.length; i++){
              System.out.print(arg[i]);
          }
          System.out.println();
      }    
运行结果:
       //此处有一个换行,当
1
123
12345

向方法中传递可变参数后,可变参数是以数组的形式保持下来的,调用可变参数也是以数组得形式调用

上列代码fun方法中可以看做把可变参数传递给了名为arg的数组,arg数组中就存放了传递过来的参数。

 

2.foreach输出

for(数据类型 变量名称:数组名称){

}

 1 public class Array {
 2     public static void main(String[] args) {
 3         int a[] = new int[10];
 4         for(int i = 0; i < a.length; i++)
 5             a[i] = i;
 6         for(int m:a){                    //用foreach输出,就相当于逐次将数组元素给变量m,
7 System.out.print(m + " "); //然后通过变量m来进行操作。 8 } 9 } 10 }
运行结果:
0 1 2 3 4 5 6 7 8 9

 

下面结合可变参数和foreach

 1 public class Array {
 2     public static void main(String[] args) {
 3         int a[] = new int[5];
 4             fun();
 5             fun(1);
 6             fun(1,2,3);
 7             fun(1,2,3,4,5);
 8     }
 9     
10     private static void fun(int...ar){
11           for(int m : ar){
12               System.out.print(m);
13           }
14           System.out.println();
15       }    
16 }
运行结果:

1
123
12345

 

1.1(java 学习笔记) 面向过程与面向对象

1.1(java 学习笔记) 面向过程与面向对象

面向过程思考时,我们会先思考具体的步骤,第一步走什么,第二步做什么。

比如电脑新建文件夹,第一步:打开电脑

                                    第二步:按下鼠标右键。

                                    第三步:找到新建选项

                                    第四步:点击新建选项下的文件夹

c 语言是典型的面向过程的编程语言,注意步骤即可。

面向过程编程思想,适合于简单的不需要协作的单独部分。

 

而现实中有很多复杂的事物,用面向过程去思考每一个步骤是不现实,比如如何制作一台电脑。

这种比较复杂的问题用步骤列出来不现实,这时就可以采用面向对象来思考。

采用面向对象的思考方式时思考的是 “电脑是怎么设计的?”

将电脑分解成一个一个对象:

   CPU

   GPU

   主板

   内存

   等对象。

为了便与协作再去找专门做 CPU 的工厂按做 CPU 的步骤(面向过程)去完成,专门做 GPU 的工厂按做 GPU 的步骤去完成。

面向对象从宏观上把握整体的结构,每一个单一的结构又由面向过程来完成。

两者之间是相辅相成的。

初学 java 有些概念不是很清楚,可能理解有偏差。不对之处还望各位指出,共同学习,共同进步。

 

今天的关于5.6java学习笔记 queue的分享已经结束,谢谢您的关注,如果想了解更多关于1.10(java学习笔记)super关键字、1.11(java学习笔记)封装、1.14(java学习笔记)数组、1.1(java 学习笔记) 面向过程与面向对象的相关知识,请在本站进行查询。

本文标签: