自学内容网 自学内容网

深入理解Java中的数组和方法

一、数组

数组是Java中用于存储固定大小的同类型元素的数据结构。它提供了一种有效的方式来组织和访问数据。

1.数组的声明和初始化方式

在Java中,有三种常见的数组声明和初始化方式

a.直接初始化数组

直接初始化数组是最简单和常用的方式之一。您可以在声明数组时直接指定其元素的初始值。

int[] numbers = {1, 2, 3, 4, 5}; // 声明并初始化一个整数数组
String[] names = {"Alice", "Bob", "Carol"}; // 声明并初始化一个字符串数组

b.动态初始化数组

动态初始化数组是在声明数组时分配内存空间,但不指定具体的初始值,而是指定数组的大小。

int[] numbers = new int[5]; // 声明一个包含5个整数的数组
double[] prices = new double[10]; // 声明一个包含10个双精度浮点数的数组
c.分步初始化数组

分步初始化数组是在声明数组后,逐个或批量为数组元素赋值的方式。

int[] numbers = new int[3];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

2.数组的访问和操作

您可以通过数组的索引来访问和修改数组中的元素。数组的索引从0开始。

int[] numbers = {1, 2, 3, 4, 5};
int firstNumber = numbers[0]; // 访问第一个元素
numbers[1] = 10; // 修改第二个元素的值

3.案例:生成一个包含唯一随机数的数组

以下代码展示了如何生成一个长度为10的数组,数组中的元素大小为1到100之间,且确保数组中的数据不重复。

package com.work;

import java.util.Random;

public class work02 {
    public static void main(String[] args) {
        Random ran = new Random(System.currentTimeMillis());

        int[] nums = new int[10];
        int[] buckets = new int[101]; // 确保[0, 100]的数字都能放进桶里

        int count = 0;
        while (count < 10) {
            int num = ran.nextInt(100) + 1;
            if (buckets[num] == 0) { // 检查是否未使用
                nums[count] = num;
                buckets[num] = 1; // 标记为已使用
                count++;
            }
        }
        for (int num : nums)
            System.out.print(num + "\t");
    }
}

二、方法

方法是Java中用于执行特定任务的代码块。它允许您将代码组织成逻辑单元,可重复使用和调用。

1.方法的声明和调用

在Java中,方法有如下声明方式:

public static int add(int a, int b) {
    return a + b;
}
方法的关键词解释
  • 修饰符:指定方法的访问权限和行为。常见的修饰符包括 publicprivateprotectedstatic 等。
  • 返回类型:指定方法返回的数据类型,可以是基本数据类型或对象类型。如果方法不返回任何值,则返回类型为 void
  • 方法名:方法的名称,用于在其他地方调用该方法。
  • 参数列表:指定方法接受的输入参数,可以有零个或多个参数。
方法的注意事项
  • 方法可以有零个或多个参数,参数之间用逗号分隔。
  • 方法可以有一个返回值,使用 return 语句返回方法执行结果。
  • 方法可以是静态的(使用 static 修饰),可以通过类名直接调用,也可以是实例方法(非静态方法),需要通过对象实例调用。

 2.案例:找出数组中的最小值和第二大值

以下代码展示了如何编写方法来找出数组中的最小值和第二大值。

package com.ffyc;

import java.util.Arrays;

public class demo8 {
    // 找出数组的第二大值
    public static int secondMax(int[] a) {
        Arrays.sort(a); // 对数组进行排序
        return a[a.length - 2]; // 返回排序后倒数第二个元素
    }

    // 找出数组的最小值
    public static int min(int[] a) {
        int m = a[0]; // 假设第一个元素为最小值
        for (int t : a)
            if (m > t)
                m = t; // 如果发现更小的值,则更新最小值
        return m;
    }

    public static void main(String[] args) {
        int[] numbers = {1, 4, 4, 5, 5, 5, 6, 3, 3, 2};

        System.out.println("数组中的最小值:" + min(numbers));
        System.out.println("数组中的第二大值:" + secondMax(numbers));
    }
}

3.不定参数

例如我想要写一个乘法的方法,但是我想多个数相乘,难道我要写n个参数吗?这时候就需要不定参数了。

package com.ffyc;

/**
 * 方法重载
 * 不定参数
 */
public class demo1 {
    //不定参数
    public static  double mul(double a,double b)
    {
        return a*b;
    }


    public static  double mul(double ...a)
    {
        double sum = 1;
        for(int i=0;i<a.length;i++)
        {
            sum*=a[i];
        }
        return sum;
    }
    public static void main(String[] args) {

        System.out.println(mul(1,2,3,4));

    }
}

4.递归

        简单来说,就是自己调用自己。需要注意的是,写递归需要注意两个点,第一,找到终止条件,第二,找到规律。一般来说,递归能做的循环也能做,递归的效率不如循环,当然我们也可以对递归做些优化处理,例如动态规划问题,但是在某些情况下,只能用递归。例如,遍历树的节点。所以掌握递归很重要。

a.案例:递归10进制转换2进制
package com.ffyc;

/**
 * 递归,10进制转换2进制
 */
public class demo4 {
    public static String tr(int n) {
        if (n == 0)
            return "0";
        else if (n == 1)
            return "1";
        else
            return tr(n >> 1) + (n % 2);

    }

    public static void main(String[] args) {

        System.out.println(tr(5));

    }
}
b.示例:递归,最大公约数
package com.ffyc;

/**
 * 递归,最大公约数
 */
public class demo6 {
    public static int gcd(int a, int b)
    {
        if (b == 0)
            return a;
        else
            return gcd(b, a % b);
    }

    public static void main(String[] args)
    {

        System.out.println(gcd(8, 12));

    }
}

5.为什么有时递归优于循环

  • 代码简洁:对于一些问题,递归可以使代码更加简洁和易读。
  • 自然表示:有些问题本身就是递归性质的,用递归可以更自然地表示和解决问题。
  • 自动处理状态:递归自动处理了状态的保存和恢复,而循环往往需要显式地使用堆栈或其他数据结构来模拟这种行为。
递归的缺点
  • 性能开销:递归调用会有函数调用的开销,特别是在递归深度较大时,会导致栈溢出。
  • 内存使用:递归调用会使用系统的调用栈,深度过大会导致栈内存不足。

虽然递归和循环大部分情况下是可以互换的,但在特定的问题域中,递归的使用会使得问题的解决更为自然和简洁。


原文地址:https://blog.csdn.net/Broken_x/article/details/140405639

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!