15.0/Java中的数组与运用

目录

第一个:什么是数组?

第二个:数组的优势

第三个:数组的初始化

数组动态初始化案例

第四个:数组的元素访问

第五个. 数组中经典案例

5.1 查找数组中最大元素和最小元素

5.2 为数组排序-选择排序

5.3 查找某个数是否在数组中

 第六个. 数组的冒泡排序

第七个.查找数组中是否存在某个元素

法一:利用equals()与for循环进行判断

法二:用asList方法


前言:

数组在Java中算是非常重要的技术之一

比如,现实中的活生生的案例

需要统计某公司员工的工资情况,例如计算平均工资、找到最高工资等。假设该公司有50名员工,假如我没有数组的话,程序首先需要声明50个变量来分别记住每位员工的工资,然后在进行操作,这样做会显得很麻烦,而且错误率也会很高。因此我们可以使用容器进行操作。将所有的数据全部存储到一个容器中,统一操作。
 

第一个:什么是数组?

数组: 一个容器,用来存一批同种类型的数据的。

容器概念

  • 容器:是将多个数据存储到一起,每个数据称为该容器的元素。
  • 生活中的容器:水杯,衣柜,教室

第二个:数组的优势

数组比变量更加简捷,方便.

举个例子: 比如,我们要做一个点名器 ↓

如果用变量来做的话,代码是这样子的 ↓

如果用数组来做的话,代码是这样子的 ↓

一对比我们发现数组的写法比变量的写法更加好用方便,

所以我们可以得出一个结论:

遇到批量数据的存储和操作时,数组比变量更适合

第三个:数组的初始化

数组的两种常见初始化方式:

  1. 动态初始化(指定长度)
  2. 静态初始化(指定内容)

    方式一:动态初始化

  3. 格式:
  4. 数组存储的数据类型[ ] 数组名字 = new 数组存储的数据类型[数组长度];
    数组存储的数据类型 数组名字[ ] = new 数组存储的数据类型[数组长度];

  1. 数组定义格式详解:
  2. 数组存储的数据类型: 创建的数组容器可以存储什么数据类型。
  3. [] : 表示数组。
  4. 数组名字:为定义的数组起个变量名,满足标识符规范,可以使用名字操作数组。
  5. new:关键字,创建数组使用的关键字。
  6. 数组存储的数据类型: 创建的数组容器可以存储什么数据类型。
  7. [长度]:数组的长度,表示数组容器中可以存储多少个元素。

注意:

使用动态初始化定义数组时,根据元素类型不同,默认值也有所不同












 

动态初始化数组中的每个元素的值都有默认值。
   int byte short long char→0
   boolean→false
   float double→0.0
   引用类型。String→null

数组动态初始化案例

案例需求:
	某歌唱比赛,需要开发一个系统:可以录入6名评委的打分,录入完毕后立即输出平均分做
	选手得分

需求分析:
	1.需要录入6名评委的分数,可以用一个数组来保存。
	   因为在评委没有录入分数之前,还不确定数组中应该存哪些数据。
	   所以可以使用数组的动态初始化
	2.遍历数组中的每一个位置,并录入分数,将分数存入数组中
	3.遍历数组中的每一个元素,对元素求和
代码如下:
import java.util.Scanner;


public class Test055 {
    public static void main(String[] args) {
        //语法: 数据类型[] 数组名=new 数据类型[长度]
        double[] arr=new double[6];
        //控制台输入分
        Scanner sc=new Scanner(System.in);
        for(int i=0;i<arr.length;i++){
            System.out.println("录入第"+(i+1)+"位评委的成绩");
            double score = sc.nextDouble();
            //把上面输入的分数赋值给数组
            arr[i]=score;
        }

        //遍历数组请求数组中所有元素的和
        double sum=0;
        for(int i=0;i<arr.length;i++){
            sum+=arr[i];
        }
        System.out.println("平均值:"+sum/arr.length);
    }
}
第四个:数组的元素访问

数组是用来存储数据的。那么数组中存储的数据又如何访问呢?

这里所说的访问,意思就是获取中数组中数据的值、或者给数组中的数据赋值。

  • 注意:数组有定长特性,长度一旦指定,不可更改。
  • 它与水杯道理相同,买了一个2升的水杯,总容量就是2升,不能多也不能少。
  • 举例:

    定义可以存储3个整数的数组容器,代码如下:

  • int[] arr = new int[3];  
    int   arr[] = new int[3];
    // 可以拆分 
    int[] arr;
    arr = new int[3];

  • 方式二: 静态初始化

    所谓静态初始化指的是:在定义数组时直接给数组中的数据赋值。

    1. 静态初始化标准格式:

    数据类型[] 变量名 = new 数据类型[]{元素1,元素2,元素3};

    按照格式定义int类型、double类型数组

  • //定义数组,用来存储多个年龄
    int[] ages = new int[]{12, 24, 36}
    //定义数组,用来存储多个成绩
    double[] scores = new double[]{89.9, 99.5, 59.5, 88.0};

    2. 静态初始化简化格式

    Java语言的设计者为了简化定义数组的写法,还为静态初始化提供了一种简化写法

    数据类型[] 变量名 = {元素1,元素2,元素3};

    使用简化格式定义int类型、double类型数组

  • //定义数组,用来存储多个年龄
    int[] ages = {12, 24, 36}
    //定义数组,用来存储多个成绩
    double[] scores = {89.9, 99.5, 59.5, 88.0};

    3. 注意哟!!

  • 定义数组时, 数据类型[] 数组名 也可写成 数据类型 数组名[]

  • //以下两种写法是等价的。但是建议大家用第一种,因为这种写法更加普遍
    int[] ages = {12, 24, 36};
    int ages[] = {12, 24, 36}

    4. 数组在计算机中的基本原理

  • 我们知道数组是怎么定义的之后,那么接下来看一下数组在计算机中的基本原理。

    我们以int[] ages = {12,24,36};这句话为例,看一下这句话到底在计算机中做了那些事情。

  • 首先,左边int[] ages 表示定义了一个数组类型的变量,变量名叫ages

  • 其次,右边{12,24,36}表示创建一个数组对象,你完全可以把它理解成一个能装数据的东西。这个对象在内存中会有一个地址值[I@4c873330,每次创建一个数组对象都会有不一样的地址值。

  • 然后,把右边的地址值[I@4c873330赋值给左边的ages变量

  • 所以,ages变量就可以通过地址值,找到数组这个东西。

这里先给大家统一几个概念,数组中存储的数据我们叫做元素;而且数组中的每一个元素都有一个编号与之对应,我们把这个编号叫做索引,这个索引是从0依次递增的整数。如下图所示

数组的索引从0到数组长度-1.
数组的长度: 数组名.length.

要想访问数组中的元素,格式如下 ↓

//数组名可以找到数组对象的地址,再通过索引就可以定位到具体的元素了
数组名[索引]

接下来用代码来演示一下

//索引:	   0   1   2
int[] arr = {12, 24, 36};
// 1、访问数组的全部数据
System.out.println(arr[0]); //12
System.out.println(arr[1]); //24
System.out.println(arr[2]); //36
//下面代码没有3索引,会出现ArrayIndexOutOfBoundsException 索引越界异常
//System.out.println(arr[3]); 

// 2、修改数组中的数据
arr[0] = 66;
arr[2] = 100;
System.out.println(arr[0]); //66
System.out.println(arr[1]); 0
System.out.println(arr[2]); //100

除了访问数组中的元素,我们可以获取数组中元素的个数,后面我们统称为数组的长度。 ↓


public class Test09 {
    //数据类型[] 数组名=new 数据类型[]{元素1,元素2,元素3};
    //数据类型[] 变量名 = {元素1,元素2,元素3}; 一定用这种方式。
    public static void main(String[] args) {
        //整数数组
        int[] arr=new int[]{1,9,10,2,5,11};
        //字符串数组
        String[] arr2=new String[]{"李白","刘德华","张学友","郭富城"};

        //简写模式。
        String[] arr3={"李白","王俊凯","易烊千玺","王源","吴韩煜"};//F4
        //小数数组

//        //数组在内存中的原理: 数组属于引用类型。内存中占用两个空间【栈和堆】。栈里面存放的是引用地址  堆里面存放的是值。
//        arr3[0]="刘德华";
//        System.out.println(arr3[3]); //访问数组arr3中索引为2的元素

        //数组中元素的个数: 数组名.length ===数组中元素的个数
        //System.out.println(arr.length);

        //遍历数组: 把数组中每个元素都获取。
        for(int i=0;i<arr3.length;i++){ //注意: 索引不能等于数组长度
            System.out.println(arr3[i]);
        }
    }
}

第五个. 数组中经典案例

5.1 查找数组中最大元素和最小元素

public class Test06 {
    public static void main(String[] args) {
        //求该数组中最大的元素
        int[] arr={10,23,43,23,56,67,12,56,67,32};
        //擂台法
        int tmp=arr[0];
        //遍历
        for(int i=0;i<arr.length;i++){
             if(tmp<arr[i]){
                 tmp=arr[i];
             }
        }

        System.out.println("最大值:"+tmp);
    }
}

5.2 为数组排序-选择排序

public class Test07 {
    public static void main(String[] args) {
        int[] arr={10,23,43,23,1,67,12,56,67,3};
        for(int i=0;i<arr.length;i++){//排序的次数
            for(int j=i+1;j<arr.length;j++){
                  if(arr[i]<arr[j]){
                       //交换位置
                       int tmp=arr[i];
                       arr[i]=arr[j];
                       arr[j]=tmp;
                  }
            }
        }
        System.out.println("排好序的数组============================");
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+"\t");

        }
    }
}

5.3 查找某个数是否在数组中

 public static void main(String[] args) {
        int[] arr={10,23,43,23,1,67,12,56,67,3};
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入你要查找的数:");
        int num=sc.nextInt();
        boolean flag=false;//表示不存在
        for(int i=0;i<arr.length;i++){
              if(num==arr[i]){
                  flag=true;
                  break;
              }
        }

        if(flag==true){
            System.out.println(num+"在数组中");
        }else{
            System.out.println(num+"不在数组中");
        }
    }

 第六个. 数组的冒泡排序

冒泡排序无疑是最出名的排序算法之一,总共有八大排序!

冒泡的代码还是相当简单的,两个循环,外层冒泡轮数,里层依次比较。

我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)

思考如何优化?

如何将数组冒泡排序?

x先看以下这么将两个数进行交换

package array;
 
import java.util.Arrays;
 
public class ArrayDemo08 {
 
    public static void main(String[] args) {
        int[] a = {1,3,6,6,4,77,66};
        
        int[] sort = sort(a);
        System.out.println(Arrays.toString(sort));
        
 
    }
    //冒泡排序
    //1.比较数组中,两个相邻的元素,如何第一个数比第二个数大,我们就交换他们的位置
    //2.每一次比较,都会产生出一个最大,或者最小值;
    //3.下一次则可以少一次排序
    //4.依次循环,直到结束!
    
    public static int[] sort(int[] array) {
        //临时变量
        int temp = 0;
        
        //外层循环,比价判断两个数。如果第一个数,比较第二个数大,则交换位置
        
        for(int i = 0;i < array.length-1;i++) {
            //内层循环,比价判断两个数,如果第一个数比第二个数大,则交换位置
            
            for(int j = 0;j<array.length-1-i;j++) {
                if(array[j+1]<array[j]) {
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
                
            }
            
        }
        return array;
    }
 
}


运行结果:

如何优化?

我们可以减少没有意义的比较

代码如下:

package array;
 
import java.util.Arrays;
 
public class ArrayDemo08 {
 
	public static void main(String[] args) {
		int[] a = {1,3,6,6,4,77,66};
		
		int[] sort = sort(a);
		System.out.println(Arrays.toString(sort));
		
 
	}
	//冒泡排序
	//1.比较数组中,两个相邻的元素,如何第一个数比第二个数大,我们就交换他们的位置
	//2.每一次比较,都会产生出一个最大,或者最小值;
	//3.下一次则可以少一次排序
	//4.依次循环,直到结束!
	
	public static int[] sort(int[] array) {
		//临时变量
		int temp = 0;
		
		//外层循环,比价判断两个数。如果第一个数,比较第二个数大,则交换位置
		
		for(int i = 0;i < array.length-1;i++) {
			
			boolean flag = false;//通过flag标识符减少没有意义的比较
			
			//内层循环,比价判断两个数,如果第一个数比第二个数大,则交换位置
			
			for(int j = 0;j<array.length-1-i;j++) {
				if(array[j+1]<array[j]) {
					temp = array[j];
					array[j] = array[j+1];
					array[j+1] = temp;
					flag = true;
				}
				
			}
			if(flag==false) {
				break;
			}
			
		}
		return array;
	}
 
}
 运行结果

第七个.查找数组中是否存在某个元素

法一:利用equals()与for循环进行判断
public class java_22 {
    public static void main(String[] args) {
//        检查数组是否包含某个元素
        String strArr[] = new String[]{"a","b","c"};
        String str = "a";
        boolean flag = new java_22().contains(strArr,str);
    }
    private boolean contains(String[] arr,String str) {
        for (int i = 0; i < arr.length; i++) {
//            equals比较字符串中所包含的内容是否相同,返回true或false
            if(arr[i].equals(str)){
                System.out.println("存在");
                return true;
            }
        }
        return false;
    }
 
}

法二:用asList方法

这个方法是将数组转成list,是JDK中java.util包中Arrays类的静态方法。

转为list之后,就可以用List的contains方法用于判断对象是否存在于列表中


import java.util.Arrays;
import java.util.List;
 
public class java_22 {
    public static void main(String[] args) {
//        检查数组是否包含某个元素
        String[] strArr = new String[]{"a","b","c"};
        String str = "a";
        boolean flag = new java_22().contains(strArr,str);
    }
//    private声明:表示当前被修饰的变量以及方法为私有的
    private boolean contains(String[] arr,String str) {
        List<String> list = Arrays.asList(arr); //将数组转为list
//    然后就可以用List的contains方法用于判断对象是否存在于列表中
        boolean result = list.contains(str);
        return result;//将结果返回出去
    }
}

法三:可以使用set集合或者stream实现

一、stream流的常见生成方式

1、Collection体系集合

使用默认方法stream()生成流, default Stream<E> stream() 


//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
 
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();

2、Map体系集合

把Map转成Set集合,间接的生成流


//Map体系的集合间接的生成流
Map<String,Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

3、数组

通过Arrays中的静态方法stream生成流


//数组可以通过Arrays中的静态方法stream生成流
String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Arrays.stream(strArray);

4、同种数据类型的多个数据

一.通过Stream接口的静态方法of(T... values)生成流


//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);

二、Stream流中间操作方法

中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作

常见方法

Stream<T> filter(Predicate predicate)    用于对流中的数据进行过滤     


//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
 
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
 
//需求1:把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("--------");
 
//需求2:把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("--------");
 
//需求3:把list集合中以张开头的,长度为3的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);

  

Stream<T> limit(long maxSize)    返回此流中的元素组成的流,截取前指定参数个数的数据
 Stream<T> skip(long n)      跳过指定参数个数的数据,返回由该流的剩余元素组成的流


//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
 
list.add("林青霞");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
 
//需求1:取前3个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------");
 
//需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------");
 
//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
  1. static <T> Stream<T> concat(Stream a, Stream b)      合并a和b两个流为一个流 
    Stream<T> distinct()   返回由该流的去重(根据Object.equals(Object) )之后的不同元素组成的流


//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
 
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
 
//需求1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
 
//需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
 
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
Stream.concat(s1,s2).forEach(System.out::println);
 
//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::println);

Stream流终结操作方法

终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作

void forEach(Consumer action)      对此流的每个元素执行操作
long count()                返回此流中的元素数


//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
 
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
 
//需求1:把集合中的元素在控制台输出
list.stream().forEach(System.out::println);
 
//需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count);

Stream流的收集操作

对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中

R collect(Collector collector)            把结果收集到集合中

工具类Collectors提供了具体的收集方式
public static <T> Collector toList()     把元素收集到List集合中 
public static <T> Collector toSet()     把元素收集到Set集合中
public static  Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中


//创建List集合对象
List<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
 
 
//需求1:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
 
//需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
List<String> names = listStream.collect(Collectors.toList());
for(String name : names) {
    System.out.println(name);
}
 
 
//创建Set集合对象
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
 
 
//需求3:得到年龄大于25的流
Stream<Integer> setStream = set.stream().filter(age -> age > 25);
 
//需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
Set<Integer> ages = setStream.collect(Collectors.toSet());
for(Integer age : ages) {
    System.out.println(age);
}
 
//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
 
//需求5:得到字符串中年龄数据大于28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s ->                         Integer.parseInt(s.split(",")[1]) > 28);
 
//需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
 
Set<String> keySet = map.keySet();
for (String key : keySet) {
    Integer value = map.get(key);
    System.out.println(key + "," + value);
}


 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光明是人的信仰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值