Java常见问题(二)

11. Java中的 throw 和 throws 有什么区别?

        在Java中,throw 和 throws 都与异常处理相关,但它们的用途和行为有显著区别。

11.1 throw 关键字
  • 作用

    • 用于在代码中显式抛出一个异常。

    • 通常用于在满足某些条件时主动抛出异常。

  • 语法

    throw 异常对象;
  • 示例

    public class Main {public static void main(String[] args) {int age = -5;if (age < 0) {throw new IllegalArgumentException("年龄不能为负数"); // 抛出异常}}
    }
  • 特点

    • throw 用于方法内部。

    • 抛出的异常必须是 Throwable 或其子类的实例。

    • 抛出异常后,程序会立即停止当前方法的执行,并将异常传递给调用者。

11.2 throws 关键字
  • 作用

    • 用于方法签名中,声明该方法可能抛出的异常类型。

    • 调用该方法时,必须处理这些异常(使用 try-catch 或继续向上抛出)。

  • 语法

    返回类型 方法名(参数列表) throws 异常类型1, 异常类型2, ... {// 方法体
    }
  • 示例

    public class Main {public static void main(String[] args) {try {readFile("file.txt");} catch (IOException e) {System.out.println("捕获异常: " + e.getMessage());}}static void readFile(String fileName) throws IOException {if (!fileName.equals("file.txt")) {throw new IOException("文件未找到"); // 抛出异常}}
    }
  • 特点

    • throws 用于方法签名中。

    • 可以声明多个异常类型,用逗号分隔。

    • 调用者必须处理这些异常,否则程序会编译失败。

11.3 throw 和 throws 的区别
特性throwthrows
用途显式抛出一个异常声明方法可能抛出的异常类型
位置方法内部方法签名中
异常对象必须是一个具体的异常对象只需要指定异常类型
调用者处理不需要在方法签名中声明调用者必须处理或继续抛出
示例throw new Exception("错误");void method() throws Exception;
11.4 使用场景
(1)throw 的使用场景
  • 当方法内部检测到某些条件不满足时,主动抛出异常。

  • 例如,参数校验、业务逻辑检查等。

(2)throws 的使用场景
  • 当方法内部可能抛出受检异常(checked exception),但不想在方法内部处理时,使用 throws 将异常传递给调用者。

  • 例如,文件操作、网络操作等可能抛出 IOException 的场景。

11.5 注意事项
  1. 受检异常 vs 非受检异常

    • 受检异常(checked exception):必须使用 throws 声明或在方法内部处理(如 IOException)。

    • 非受检异常(unchecked exception):不需要使用 throws 声明(如 NullPointerExceptionIllegalArgumentException)。

  2. 方法重写时的 throws

    • 子类重写父类方法时,throws 声明的异常类型不能比父类方法更宽泛。

    • 例如,父类方法声明 throws IOException,子类方法可以声明 throws FileNotFoundExceptionFileNotFoundException 是 IOException 的子类),但不能声明 throws Exception

  3. throw 和 throws 的结合使用

    • 可以在方法内部使用 throw 抛出异常,同时在方法签名中使用 throws 声明异常类型。

总结
  • throw:用于在代码中显式抛出一个异常。

  • throws:用于方法签名中,声明该方法可能抛出的异常类型。

12. Java中的 interface 和 abstract class 有什么区别?

        在Java中,interface 和 abstract class 都是用于实现抽象和多态的重要机制,但它们在设计和使用上有显著的区别。

12.1 定义
  • 接口(Interface)

    • 是一种完全抽象的类,只能包含抽象方法(Java 8 之前)。

    • 从 Java 8 开始,接口可以包含默认方法(default 方法)和静态方法。

    • 从 Java 9 开始,接口可以包含私有方法。

  • 抽象类(Abstract Class)

    • 是一种部分抽象的类,可以包含抽象方法和具体方法。

    • 可以定义成员变量、构造器、普通方法和抽象方法。

12.2 主要区别
特性接口(Interface)抽象类(Abstract Class)
方法实现Java 8 之前只能包含抽象方法;Java 8 开始可以包含默认方法和静态方法可以包含抽象方法和具体方法
成员变量只能包含常量(默认是 public static final可以包含普通成员变量和常量
构造器不能定义构造器可以定义构造器
多继承支持多继承(一个类可以实现多个接口)不支持多继承(一个类只能继承一个抽象类)
默认访问修饰符方法默认是 public abstract方法可以是 publicprotected 或默认访问修饰符
设计目的定义行为规范(“能做什么”)定义类的部分实现(“是什么”和“能做什么”)
12.3 使用场景
(1)接口的使用场景
  • 定义一组行为规范,强调“能做什么”。

  • 需要多继承时(一个类可以实现多个接口)。

  • 适用于定义通用的功能,例如:

    • Runnable 接口定义线程任务。

    • Comparable 接口定义对象的比较规则。

(2)抽象类的使用场景
  • 定义部分实现,强调“是什么”和“能做什么”。

  • 需要共享代码或状态时(抽象类可以包含成员变量和具体方法)。

  • 适用于定义具有共同特征的类,例如:

    • 动物类(Animal)可以定义抽象方法 sound(),子类(如 DogCat)实现具体的叫声。

12.4 示例代码

接口示例

interface Flyable {void fly(); // 抽象方法default void land() { // 默认方法System.out.println("正在降落");}static void altitude() { // 静态方法System.out.println("飞行高度");}
}class Bird implements Flyable {public void fly() {System.out.println("鸟在飞翔");}
}public class Main {public static void main(String[] args) {Bird bird = new Bird();bird.fly(); // 输出: 鸟在飞翔bird.land(); // 输出: 正在降落Flyable.altitude(); // 输出: 飞行高度}
}

抽象类示例

abstract class Animal {String name;Animal(String name) {this.name = name;}abstract void sound(); // 抽象方法void sleep() { // 具体方法System.out.println(name + " 正在睡觉");}
}class Dog extends Animal {Dog(String name) {super(name);}void sound() {System.out.println(name + " 汪汪叫");}
}public class Main {public static void main(String[] args) {Dog dog = new Dog("小黑");dog.sound(); // 输出: 小黑 汪汪叫dog.sleep(); // 输出: 小黑 正在睡觉}
}
12.6 如何选择接口还是抽象类?
  • 使用接口

    • 需要定义一组行为规范。

    • 需要多继承。

    • 不关心具体实现细节。

  • 使用抽象类

    • 需要共享代码或状态。

    • 需要定义部分实现。

    • 需要构造器或非静态成员变量。

13. Java中的 volatile 关键字有什么作用?

        在 Java 中,volatile 关键字用于修饰变量,主要作用是确保变量的可见性和禁止指令重排序。

13.1 可见性
  • 作用:当一个线程修改了 volatile 变量的值,其他线程能立即看到最新的值。

  • 机制volatile 变量不会被线程缓存,所有读写操作都直接在主内存中进行,保证了多线程环境下的可见性。

13.2 禁止指令重排序
  • 作用:防止 JVM 和处理器对指令进行重排序,确保代码执行顺序与编写顺序一致。

  • 机制volatile 变量的读写操作前后会插入内存屏障,防止重排序。

使用场景

  • 状态标志:用于标记线程是否继续运行。

    volatile boolean running = true;public void run() {while (running) {// 执行任务}
    }public void stop() {running = false;
    }
  • 双重检查锁定(Double-Checked Locking):用于单例模式中,确保实例的唯一性。

    class Singleton {private volatile static Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
    }

注意事项

  • 不保证原子性volatile 不能保证复合操作的原子性,如 i++

  • 性能影响:频繁读写 volatile 变量可能影响性能,因为每次操作都直接访问主内存。

总结

  volatile 关键字主要用于确保变量的可见性和防止指令重排序,适用于状态标志和双重检查锁定等场景,但不适用于需要原子性操作的场合。

14. Java中的 synchronized 关键字有什么作用?

        在 Java 中,synchronized 关键字用于实现线程同步,确保多个线程在访问共享资源时的线程安全。

14.1 互斥性(Mutual Exclusion)
  • 作用synchronized 修饰的代码块或方法在同一时间只能被一个线程执行。

  • 机制:通过获取对象的锁(monitor lock)来实现互斥。当一个线程进入 synchronized 代码块时,其他线程必须等待锁释放后才能进入。

14.2 可见性(Visibility)
  • 作用:确保线程对共享变量的修改对其他线程可见。

  • 机制:在 synchronized 代码块或方法执行完成后,会将线程本地内存中的变量值刷新到主内存中;在进入 synchronized 代码块或方法时,会从主内存中读取最新的变量值。

使用方式

synchronized 可以修饰以下两种形式:

1. 修饰实例方法

  • 锁对象是当前实例(this)。

  • 示例:

    public synchronized void method() {// 线程安全的代码
    }

2. 修饰静态方法

  • 锁对象是当前类的 Class 对象。

  • 示例:

    public static synchronized void staticMethod() {// 线程安全的代码
    }

3. 修饰代码块

  • 需要显式指定锁对象。

  • 示例:

    public void method() {synchronized (this) { // 锁对象是当前实例// 线程安全的代码}
    }
    使用场景
  • 保护共享资源

    • 当多个线程需要访问或修改共享资源时,使用 synchronized 可以避免数据不一致问题。

    • 示例:

      public class Counter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
      }
  • 实现线程安全的单例模式

    • 使用 synchronized 确保单例对象的唯一性。

    • 示例:

      public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
      }
  • 线程间通信

    • 结合 wait() 和 notify() 方法,实现线程间的协作。

    • 示例:

      public class SharedResource {private boolean isReady = false;public synchronized void waitUntilReady() throws InterruptedException {while (!isReady) {wait(); // 释放锁并等待}}public synchronized void setReady() {isReady = true;notifyAll(); // 唤醒等待的线程}
      }
      注意事项
    • 性能开销:

      • synchronized 会引入锁竞争,可能导致线程阻塞,影响性能。

      • 在高并发场景下,可以考虑使用更高效的并发工具(如 ReentrantLock 或 java.util.concurrent 包中的类)。

    • 死锁风险

      • 如果多个线程互相持有对方需要的锁,可能导致死锁。

      • 示例:

        // 线程1
        synchronized (lockA) {synchronized (lockB) {// 操作}
        }// 线程2
        synchronized (lockB) {synchronized (lockA) {// 操作}
        }
    • 锁的范围

      • 尽量缩小同步代码块的范围,避免不必要的性能损耗。

总结

  synchronized 关键字是 Java 中最基本的线程同步机制,用于实现互斥性和可见性。它适用于保护共享资源、实现线程安全的单例模式以及线程间通信等场景。但在高并发场景下,需要注意性能开销和死锁风险,必要时可以使用更高级的并发工具。

15. Java中的 transient 关键字有什么作用?

        在 Java 中,transient 关键字用于修饰类的成员变量,其主要作用是阻止该变量被序列化。具体来说,当一个对象被序列化时,transient 修饰的变量不会被包含在序列化的数据中。

15.1 作用
  • 阻止序列化transient 修饰的变量在对象序列化时会被忽略,不会被保存到文件或通过网络传输。

  • 默认值:在反序列化时,transient 变量的值会被设置为默认值(如 int 类型为 0,对象类型为 null)。

15.2 使用场景
  1. 敏感信息

    • 如果某些变量包含敏感信息(如密码、密钥等),可以使用 transient 修饰,避免序列化时泄露。

    • 示例:

      public class User implements Serializable {private String username;private transient String password; // 不会被序列化// 构造方法、getter 和 setter
      }
  2. 临时数据

    • 如果某些变量是临时数据或可以通过其他数据计算得出,可以使用 transient 修饰,避免不必要的序列化。

    • 示例:

      public class Data implements Serializable {private int value;private transient int cachedResult; // 临时缓存,不需要序列化public int computeResult() {if (cachedResult == 0) {cachedResult = value * 2; // 假设这是一个计算过程}return cachedResult;}
      }
  3. 不可序列化的对象

    • 如果某个成员变量是不可序列化的对象(如 Thread 或 InputStream),可以使用 transient 修饰,避免序列化时抛出 NotSerializableException

    • 示例:

      public class AppState implements Serializable {private String appName;private transient Thread workerThread; // 不可序列化的对象
      }
15.3 注意事项
  1. 反序列化时的初始化

    • 反序列化时,transient 变量的值会被设置为默认值。如果需要恢复这些变量的值,可以自定义 readObject 方法。

    • 示例:

      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject(); // 默认反序列化this.password = "defaultPassword"; // 手动初始化 transient 变量
      }
  2. 与静态变量的区别

    • transient 修饰的是实例变量,而静态变量(static)本身就不会被序列化,因此不需要使用 transient 修饰。

总结

  transient 关键字用于阻止变量被序列化,适用于保护敏感信息、避免序列化临时数据或不可序列化的对象。反序列化时,transient 变量的值会被设置为默认值,如果需要恢复其值,可以自定义 readObject 方法。

16. Java中的 Comparable 和 Comparator 有什么区别?

        在 Java 中,Comparable 和 Comparator 都是用于对象排序的接口,但它们的用途和实现方式有所不同。

16.1 Comparable
  • 定义Comparable 是一个接口,定义在 java.lang 包中。

  • 作用:用于实现对象的自然排序(即默认排序规则)。

  • 方法:需要实现 compareTo(T o) 方法。

  • 使用场景:当一个类有明确的自然排序规则时,可以实现 Comparable 接口。

  • 示例

public class Person implements Comparable<Person> {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Person other) {return this.age - other.age; // 按年龄排序}@Overridepublic String toString() {return name + " (" + age + ")";}public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));Collections.sort(people); // 使用自然排序System.out.println(people); // 输出:[Bob (25), Alice (30), Charlie (35)]}
}
16.2 Comparator
  • 定义Comparator 是一个接口,定义在 java.util 包中。

  • 作用:用于实现对象的定制排序(即灵活的排序规则)。

  • 方法:需要实现 compare(T o1, T o2) 方法。

  • 使用场景

    • 当一个类没有实现 Comparable 接口时,可以通过 Comparator 进行排序。

    • 当需要多种排序规则时,可以使用 Comparator

  • 示例

import java.util.*;public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + " (" + age + ")";}public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 Comparator 按姓名排序Comparator<Person> nameComparator = new Comparator<Person>() {@Overridepublic int compare(Person p1, Person p2) {return p1.name.compareTo(p2.name);}};Collections.sort(people, nameComparator);System.out.println(people); // 输出:[Alice (30), Bob (25), Charlie (35)]}
}
16.3 区别对比
特性ComparableComparator
包名java.langjava.util
方法compareTo(To)compare(To1, To2)
排序规则自然排序(默认排序规则)定制排序(灵活排序规则)
实现位置在类内部实现在类外部实现
使用场景单一排序规则多种排序规则
修改排序规则需要修改类的代码不需要修改类的代码
示例Collections.sort(list)Collections.sort(list, comparator)
16.4 使用建议
  • 使用 Comparable

    • 当类有明确的自然排序规则时。

    • 例如,String 和 Integer 类都实现了 Comparable,因为它们有明确的排序规则。

  • 使用 Comparator

    • 当需要多种排序规则时。

    • 当无法修改类的源代码时(例如,使用第三方库的类)。

    • 当需要临时定义排序规则时。

总结
  • Comparable 用于定义对象的自然排序规则,适合单一排序场景。

  • Comparator 用于定义灵活的排序规则,适合多种排序场景。

17. Java中的 instanceof 关键字有什么作用?

        在 Java 中,instanceof 是一个二元操作符,用于检查一个对象是否是指定类型(类、接口或子类)的实例

17.1 作用
  • 类型检查:判断一个对象是否属于某个类或其子类、接口的实现类。

  • 避免类型转换异常:在类型转换之前使用 instanceof 进行检查,可以避免 ClassCastException

17.2 语法
object instanceof Type
  • object:需要检查的对象。

  • Type:目标类型(类、接口或子类)。

  • 返回值true 或 false

17.3 使用场景

1. 类型检查

  • 在需要判断对象的实际类型时使用。

  • 示例:

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}public class Main {public static void main(String[] args) {Animal myDog = new Dog();Animal myCat = new Cat();System.out.println(myDog instanceof Dog); // trueSystem.out.println(myDog instanceof Animal); // trueSystem.out.println(myCat instanceof Dog); // false}
}

2. 避免类型转换异常

  • 在类型转换之前使用 instanceof 进行检查,确保转换的安全性。

  • 示例:

Animal animal = new Dog();if (animal instanceof Dog) {Dog dog = (Dog) animal; // 安全转换System.out.println("This is a Dog.");
} else {System.out.println("This is not a Dog.");
}

3. 多态场景下的类型判断

  • 在处理多态对象时,instanceof 可以帮助确定对象的实际类型。

  • 示例:

public void checkAnimal(Animal animal) {if (animal instanceof Dog) {System.out.println("This is a Dog.");} else if (animal instanceof Cat) {System.out.println("This is a Cat.");} else {System.out.println("This is an unknown Animal.");}
}

4. 接口实现检查

  • 检查对象是否实现了某个接口。

  • 示例:

interface Swimmable {}
class Fish implements Swimmable {}
class Bird {}public class Main {public static void main(String[] args) {Swimmable fish = new Fish();Bird bird = new Bird();System.out.println(fish instanceof Swimmable); // trueSystem.out.println(bird instanceof Swimmable); // false}
}
17.4 注意事项
  1. null 检查

    • 如果对象为 nullinstanceof 会返回 false

    • 示例:

      Animal animal = null;
      System.out.println(animal instanceof Animal); // false
  2. 泛型类型擦除

    • 由于 Java 泛型的类型擦除机制,instanceof 不能直接用于泛型类型。

    • 示例:

      List<String> list = new ArrayList<>();
      // 以下代码无法通过编译
      // System.out.println(list instanceof List<String>);
  3. 性能影响

    • instanceof 的性能通常较好,但在高频调用时可能会影响性能。

总结

  instanceof 关键字用于检查对象是否属于某个类型,常用于类型检查、避免类型转换异常以及多态场景下的类型判断。它是 Java 中实现类型安全的重要工具,但在使用时需要注意 null 值和泛型类型擦除的限制。

18. Java中的 break 和 continue 有什么区别?

        在 Java 中,break 和 continue 都是用于控制循环流程的关键字,但它们的作用和行为有所不同。

18.1 break
  • 作用:立即终止当前循环(forwhiledo-while 或 switch 语句),并跳出循环体。

  • 使用场景

    • 当满足某个条件时,提前结束循环。

    • 在 switch 语句中,用于跳出 case 分支。

  • 示例

    for (int i = 1; i <= 10; i++) {if (i == 5) {break; // 当 i 等于 5 时,终止循环}System.out.println(i);
    }
    // 输出:1 2 3 4
18.2 continue
  • 作用:跳过当前循环的剩余代码,直接进入下一次循环迭代。

  • 使用场景

    • 当满足某个条件时,跳过当前迭代,继续执行下一次循环。

  • 示例

for (int i = 1; i <= 5; i++) {if (i == 3) {continue; // 当 i 等于 3 时,跳过本次循环}System.out.println(i);
}
// 输出:1 2 4 5
18.3 区别对比
特性breakcontinue
作用终止整个循环跳过当前迭代,继续下一次循环
使用场景提前结束循环跳过某些特定条件的迭代
循环行为循环完全结束循环继续执行,但跳过当前迭代
适用语句forwhiledo-whileswitchforwhiledo-while
18.4 嵌套循环中的使用
  • break:默认只跳出当前所在的循环。如果需要跳出外层循环,可以使用带标签的 break

  • continue:默认只跳过当前循环的当前迭代。如果需要跳过外层循环的当前迭代,可以使用带标签的 continue

带标签的 break 示例:

outerLoop:
for (int i = 1; i <= 3; i++) {for (int j = 1; j <= 3; j++) {if (i == 2 && j == 2) {break outerLoop; // 跳出外层循环}System.out.println("i=" + i + ", j=" + j);}
}
// 输出:
// i=1, j=1
// i=1, j=2
// i=1, j=3
// i=2, j=1

带标签的 continue 示例:

outerLoop:
for (int i = 1; i <= 3; i++) {for (int j = 1; j <= 3; j++) {if (i == 2 && j == 2) {continue outerLoop; // 跳过外层循环的当前迭代}System.out.println("i=" + i + ", j=" + j);}
}
// 输出:
// i=1, j=1
// i=1, j=2
// i=1, j=3
// i=2, j=1
// i=3, j=1
// i=3, j=2
// i=3, j=3
总结
  • break:用于完全终止循环,适用于提前结束循环或跳出 switch 语句。

  • continue:用于跳过当前迭代,继续执行下一次循环,适用于跳过某些特定条件的迭代。

  • 在嵌套循环中,可以使用带标签的 break 和 continue 来控制外层循环的行为。

19. Java中的 Math 类有哪些常用方法?

        Java 中的 Math 类提供了许多用于数学运算的静态方法。

19.1 基本运算
  • abs(int a)abs(long a)abs(float a)abs(double a)
    返回参数的绝对值。

  • max(int a, int b)max(long a, long b)max(float a, float b)max(double a, double b)
    返回两个参数中的较大值。

  • min(int a, int b)min(long a, long b)min(float a, float b)min(double a, double b)
    返回两个参数中的较小值。

19.2 指数和对数
  • pow(double a, double b)
    返回 a 的 b 次方。

  • sqrt(double a)
    返回 a 的平方根。

  • exp(double a)
    返回自然对数底数 e 的 a 次方。

  • log(double a)
    返回 a 的自然对数(以 e 为底)。

  • log10(double a)
    返回 a 的以 10 为底的对数。

19.3 三角函数
  • sin(double a)
    返回角度的正弦值(角度以弧度表示)。

  • cos(double a)
    返回角度的余弦值(角度以弧度表示)。

  • tan(double a)
    返回角度的正切值(角度以弧度表示)。

  • asin(double a)
    返回 a 的反正弦值(结果以弧度表示)。

  • acos(double a)
    返回 a 的反余弦值(结果以弧度表示)。

  • atan(double a)
    返回 a 的反正切值(结果以弧度表示)。

  • atan2(double y, double x)
    返回从直角坐标 (x, y) 到极坐标 (r, theta) 的转换角度 theta

19.4 舍入运算
  • ceil(double a)
    返回大于或等于 a 的最小整数(向上取整)。

  • floor(double a)
    返回小于或等于 a 的最大整数(向下取整)。

  • round(float a)round(double a)
    返回最接近 a 的整数(四舍五入)。

19.5 随机数
  • random()
    返回一个 [0.0, 1.0) 范围内的伪随机 double 值。

19.6 其他
  • toRadians(double angdeg)
    将角度转换为弧度。

  • toDegrees(double angrad)
    将弧度转换为角度。

  • hypot(double x, double y)
    返回 sqrt(x² + y²),即直角三角形的斜边长度。

  • copySign(double magnitude, double sign)
    返回一个与 sign 同符号的 magnitude 值。

  • nextAfter(double start, double direction)
    返回与 start 相邻的、朝向 direction 的浮点数。

  • nextUp(double d)
    返回比 d 大的最小浮点数。

  • nextDown(double d)
    返回比 d 小的最大浮点数。

20. Java中的 Arrays 类有哪些常用方法?

  java.util.Arrays 类是 Java 中用于操作数组的工具类,提供了许多静态方法来处理数组。

20.1 排序
  • sort(array): 对数组进行升序排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.sort(arr);
    // arr 现在是 [1, 2, 3, 4, 5]
  • sort(array, fromIndex, toIndex): 对数组的指定范围进行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.sort(arr, 1, 4);
    // arr 现在是 [5, 1, 3, 4, 2]
20.2 二分查找
  • binarySearch(array, key): 在已排序的数组中使用二分查找法查找指定元素,返回索引。如果未找到,返回负数。

    int[] arr = {1, 2, 3, 4, 5};
    int index = Arrays.binarySearch(arr, 3);
    // index 是 2
  • binarySearch(array, fromIndex, toIndex, key): 在数组的指定范围内进行二分查找。

    int[] arr = {1, 2, 3, 4, 5};
    int index = Arrays.binarySearch(arr, 1, 4, 3);
    // index 是 2
20.3 比较
  • equals(array1, array2): 比较两个数组是否相等(元素顺序和值相同)。

    int[] arr1 = {1, 2, 3};
    int[] arr2 = {1, 2, 3};
    boolean isEqual = Arrays.equals(arr1, arr2);
    // isEqual 是 true
20.4 填充
  • fill(array, value): 将数组的所有元素填充为指定值。

    int[] arr = new int[5];
    Arrays.fill(arr, 10);
    // arr 现在是 [10, 10, 10, 10, 10]
  • fill(array, fromIndex, toIndex, value): 将数组的指定范围填充为指定值。

    int[] arr = new int[5];
    Arrays.fill(arr, 1, 4, 10);
    // arr 现在是 [0, 10, 10, 10, 0]
20.5 复制
  • copyOf(original, newLength): 复制数组,指定新数组的长度。

    int[] arr = {1, 2, 3};
    int[] newArr = Arrays.copyOf(arr, 5);
    // newArr 现在是 [1, 2, 3, 0, 0]
  • copyOfRange(original, from, to): 复制数组的指定范围。

    int[] arr = {1, 2, 3, 4, 5};
    int[] newArr = Arrays.copyOfRange(arr, 1, 4);
    // newArr 现在是 [2, 3, 4]
20.6 转换为字符串
  • toString(array): 将数组转换为字符串表示形式。

    int[] arr = {1, 2, 3};
    String str = Arrays.toString(arr);
    // str 是 "[1, 2, 3]"
20.7 哈希码
  • hashCode(array): 返回数组的哈希码。

    int[] arr = {1, 2, 3};
    int hashCode = Arrays.hashCode(arr);
20.8 流操作
  • stream(array): 将数组转换为流。

    int[] arr = {1, 2, 3};
    IntStream stream = Arrays.stream(arr);
20.9 并行排序
  • parallelSort(array): 对数组进行并行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.parallelSort(arr);
    // arr 现在是 [1, 2, 3, 4, 5]
  • parallelSort(array, fromIndex, toIndex): 对数组的指定范围进行并行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.parallelSort(arr, 1, 4);
    // arr 现在是 [5, 1, 3, 4, 2]
20.10 比较器排序
  • sort(array, comparator): 使用自定义比较器对数组进行排序。

    String[] arr = {"apple", "banana", "cherry"};
    Arrays.sort(arr, (a, b) -> b.compareTo(a));
    // arr 现在是 ["cherry", "banana", "apple"]
20.11 并行前缀计算
  • parallelPrefix(array, op): 对数组进行并行前缀计算。

    int[] arr = {1, 2, 3, 4};
    Arrays.parallelPrefix(arr, (a, b) -> a + b);
    // arr 现在是 [1, 3, 6, 10]
20.12 集合转换
  • asList(array): 将数组转换为固定大小的列表。

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
// list 是 ["a", "b", "c"]

    21. Java中的 Collections 类有哪些常用方法?

      java.util.Collections 类是 Java 中用于操作集合(如 ListSetMap 等)的工具类,提供了许多静态方法来处理集合。

    21.1 排序
    • sort(list): 对列表进行升序排序。

      List<Integer> list = Arrays.asList(5, 3, 1, 4, 2);
      Collections.sort(list);
      // list 现在是 [1, 2, 3, 4, 5]
    • sort(list, comparator): 使用自定义比较器对列表进行排序。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, (a, b) -> b.compareTo(a));
      // list 现在是 ["cherry", "banana", "apple"]
    21.2 二分查找
    • binarySearch(list, key): 在已排序的列表中使用二分查找法查找指定元素,返回索引。如果未找到,返回负数。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int index = Collections.binarySearch(list, 3);
      // index 是 2
    • binarySearch(list, key, comparator): 使用自定义比较器在已排序的列表中进行二分查找。

      List<String> list = Arrays.asList("cherry", "banana", "apple");
      int index = Collections.binarySearch(list, "banana", (a, b) -> b.compareTo(a));
      // index 是 1
    21.3 反转
    • reverse(list): 反转列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.reverse(list);
      // list 现在是 [5, 4, 3, 2, 1]
    21.4 随机打乱
    • shuffle(list): 随机打乱列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.shuffle(list);
      // list 现在是随机顺序,例如 [3, 1, 5, 2, 4]
    • shuffle(list, random): 使用指定的随机源打乱列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.shuffle(list, new Random());
      // list 现在是随机顺序,例如 [4, 2, 1, 5, 3]
    21.5 填充
    • fill(list, value): 将列表的所有元素填充为指定值。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.fill(list, 10);
      // list 现在是 [10, 10, 10, 10, 10]
    21.6 复制
    • copy(dest, src): 将源列表中的元素复制到目标列表中。

      List<Integer> src = Arrays.asList(1, 2, 3);
      List<Integer> dest = Arrays.asList(4, 5, 6, 7, 8);
      Collections.copy(dest, src);
      // dest 现在是 [1, 2, 3, 7, 8]
    21.7 最小值和最大值
    • min(collection): 返回集合中的最小元素。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int min = Collections.min(list);
      // min 是 1
    • max(collection): 返回集合中的最大元素。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int max = Collections.max(list);
      // max 是 5
    • min(collection, comparator): 使用自定义比较器返回集合中的最小元素。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      String min = Collections.min(list, (a, b) -> b.compareTo(a));
      // min 是 "cherry"
    • max(collection, comparator): 使用自定义比较器返回集合中的最大元素。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      String max = Collections.max(list, (a, b) -> b.compareTo(a));
      // max 是 "apple"
    21.8 替换
    • replaceAll(list, oldVal, newVal): 将列表中的所有旧值替换为新值。

      List<String> list = Arrays.asList("apple", "banana", "apple");
      Collections.replaceAll(list, "apple", "orange");
      // list 现在是 ["orange", "banana", "orange"]
    21.9 频率
    • frequency(collection, obj): 返回集合中指定元素的出现次数。

      List<String> list = Arrays.asList("apple", "banana", "apple");
      int freq = Collections.frequency(list, "apple");
      // freq 是 2
    21.10 不可变集合
    • unmodifiableCollection(collection): 返回一个不可修改的集合视图。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collection<String> unmodifiableList = Collections.unmodifiableCollection(list);
      // unmodifiableList 是不可修改的
    • unmodifiableList(list): 返回一个不可修改的列表视图。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      List<String> unmodifiableList = Collections.unmodifiableList(list);
      // unmodifiableList 是不可修改的
    • unmodifiableSet(set): 返回一个不可修改的集合视图。

      Set<String> set = new HashSet<>(Arrays.asList("apple", "banana", "cherry"));
      Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
      // unmodifiableSet 是不可修改的
    • unmodifiableMap(map): 返回一个不可修改的映射视图。

      Map<String, Integer> map = new HashMap<>();
      map.put("apple", 1);
      map.put("banana", 2);
      Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(map);
      // unmodifiableMap 是不可修改的
    21.11 同步集合
    • synchronizedCollection(collection): 返回一个线程安全的集合。

      Collection<String> collection = new ArrayList<>();
      Collection<String> syncCollection = Collections.synchronizedCollection(collection);
      // syncCollection 是线程安全的
    • synchronizedList(list): 返回一个线程安全的列表。

      List<String> list = new ArrayList<>();
      List<String> syncList = Collections.synchronizedList(list);
      // syncList 是线程安全的
    • synchronizedSet(set): 返回一个线程安全的集合。

      Set<String> set = new HashSet<>();
      Set<String> syncSet = Collections.synchronizedSet(set);
      // syncSet 是线程安全的
    • synchronizedMap(map): 返回一个线程安全的映射。

      Map<String, Integer> map = new HashMap<>();
      Map<String, Integer> syncMap = Collections.synchronizedMap(map);
      // syncMap 是线程安全的
    21.12 单元素集合
    • singletonList(obj): 返回一个只包含指定对象的不可变列表。

      List<String> list = Collections.singletonList("apple");
      // list 是 ["apple"]
    • singletonSet(obj): 返回一个只包含指定对象的不可变集合。

      Set<String> set = Collections.singletonSet("apple");
      // set 是 ["apple"]
    • singletonMap(key, value): 返回一个只包含指定键值对的不可变映射。

      Map<String, Integer> map = Collections.singletonMap("apple", 1);
      // map 是 {"apple": 1}
    21.13 空集合
    • emptyList(): 返回一个空的不可变列表。

      List<String> list = Collections.emptyList();
      // list 是 []
    • emptySet(): 返回一个空的不可变集合。

      Set<String> set = Collections.emptySet();
      // set 是 []
    • emptyMap(): 返回一个空的不可变映射。

      Map<String, Integer> map = Collections.emptyMap();
      // map 是 {}
    21.14 检查集合是否为空
    • isEmpty(collection): 检查集合是否为空。

      List<String> list = new ArrayList<>();
      boolean isEmpty = Collections.isEmpty(list);
      // isEmpty 是 true
    21.15 反转比较器
    • reverseOrder(): 返回一个反转自然顺序的比较器。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, Collections.reverseOrder());
      // list 现在是 ["cherry", "banana", "apple"]
    • reverseOrder(comparator): 返回一个反转指定比较器顺序的比较器。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, Collections.reverseOrder(String.CASE_INSENSITIVE_ORDER));
      // list 现在是 ["cherry", "banana", "apple"]

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21296.html

    如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    Deepseek 与 ChatGPT:AI 浪潮中的双子星较量

    引言 在人工智能飞速发展的当下&#xff0c;AI 语言模型成为了人们关注的焦点。Deepseek 与 ChatGPT 作为其中的佼佼者&#xff0c;各自展现出独特的魅力&#xff0c;引领着 AI 技术的发展潮流。今天&#xff0c;就让我们深入探讨这两款模型&#xff0c;看看它们在 AI 领域中是…

    QT事件循环

    文章目录 主事件循环事件循环事件调度器事件处理投递事件发送事件 事件循环的嵌套线程的事件循环deleteLater与事件循环QEventLoop类QEventLoop应用等待一段时间同步操作模拟模态对话框 参考 本文主要对QT中的事件循环做简单介绍和使用 Qt作为一个跨平台的UI框架&#xff0c;其…

    解决DeepSeek服务器繁忙问题的实用指南

    目录 简述 1. 关于服务器繁忙 1.1 服务器负载与资源限制 1.2 会话管理与连接机制 1.3 客户端配置与网络问题 2. 关于DeepSeek服务的备用选项 2.1 纳米AI搜索 2.2 硅基流动 2.3 秘塔AI搜索 2.4 字节跳动火山引擎 2.5 百度云千帆 2.6 英伟达NIM 2.7 Groq 2.8 Firew…

    进程等待和进程程序替换

    进程控制 进程等待进程程序替换 进程等待 如果子进程没有退出 而父进程在进行执行waitpid进行等待&#xff0c;阻塞等待&#xff0c; 进程阻塞了 在等待某种条件发生&#xff08;子进程退出&#xff09; 进程程序替换 1 #include <stdio.h>2 #include <unistd.h>3…

    UEFI Spec 学习笔记---6 - Block Translation Table (BTT) Layout

    6.1 Block Translation Table (BTT) Background 定义个一个连续地址的非易失性的namespace&#xff0c;就是将一整个namespace 拆分成一个个block&#xff0c;其中的地址保存至BBT&#xff08;块转换表&#xff09;&#xff0c;这样可以防止扇区撕裂&#xff08;由于电源问题导…

    SAP 代码扫描工具

    描述&#xff1a; ZSCANNER是一个先进的代码分析工具&#xff0c;旨在提供对程序和功能模块内部工作的全面见解。它揭示了代码的技术细节&#xff0c;包括正在创建、读取、更新或删除的数据表&#xff08;CRUD操作&#xff09;&#xff0c;以及正在调用的类、功能模块和BAPI&a…

    c语言基础第12节《函数的调用》

    c语言基础10 函数 函数的调用 调用方式 ①函数语句&#xff1a; test(); // 对于无返回值的函数&#xff0c;直接调用 int res max(2,4); // 对于有返回值的函数&#xff0c;一般需要再主调函数中接收被调函数的返回值。②函数表达式&#xff1a; 4 max(2,4) scanf(&qu…

    C++:iterator迭代器失效

    说明&#xff1a;这里拿 vector 举例。 原因一&#xff1a;扩容导致迭代器失效 // 迭代器失效 void insert(iterator pos, const T& x) {assert(pos > _start);assert(pos < _finish);// 满了就扩容if (_finish _end_of_storage){reserve(capacity() 0 ? 4 : ca…

    QT之改变鼠标样式

    QT改变鼠标图片 资源路径如下 代码实现 QPixmap customCursorPixmap(":/images/mouse.png");QCursor customCursor(customCursorPixmap);QWidget::setCursor(customCursor); // 可以设置为整个窗口或特定控件QWidget::setCursor(); // 设置为透明光标&#xff0c…

    用DeepSeek零基础预测《哪吒之魔童闹海》票房——从数据爬取到模型实战

    系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 **一、为什么要预测票房&#xff1f;****二、准备工作****三、实战步骤详解****Step 1&#xff1a;数据爬取与清洗&am…

    高并发下秒杀系统的设计

    文章目录 1 业界通用做法1.1 压力分摊1.2 RedisMySQL1.3 Inventory Hint1.4 压力分摊RedisMQ 2 Redis MQ 解决高并发下的秒杀场景2.1 Redis库存预扣减2.1.1 lua脚本执行流程&#xff1a;2.1.2 Lua脚本主要做了几件事&#xff1a; 2.2 MySQL库存扣减2.3 记录操作流水的原因 3 I…

    双重差分学习笔记

    双重差分适用的研究场景&#xff1a; 研究某项政策或者冲击造成的影响 例如&#xff0c;某某小学在2024.12.12日颁布了小红花激励措施&#xff0c;我们要研究这项措施对学生成绩的影响&#xff0c;此时&#xff0c;就可以使用双重差分模型。 双重差分适用的数据类型&#xf…

    深入理解 C++17 中的 std::atomic<T>::is_always_lock_free

    文章目录 原子操作与锁无关性&#xff08;Lock-Free&#xff09;锁无关性&#xff08;Lock-Free&#xff09;无锁&#xff08;Lock-Free&#xff09;与无阻塞&#xff08;Wait-Free&#xff09; std::atomic<T>::is_always_lock_free 是什么&#xff1f;truefalse与 is_l…

    VSCode 中 Git 添加了多个远端,如何设置默认远端

    VSCode 中 Git 添加了多个远端&#xff0c;如何设置默认远端 查看分支&#xff1a;设置默认远端手动指定远端 查看分支&#xff1a; * 表示当前默认远端 git branch -vv* master a1b2c3d [origin/main] Fix typo dev d4e5f6g [upstream/dev] Add feature设置默认远端 将本…

    一文讲清 AIO BIO NIO的区别

    引言 在 Java 编程中&#xff0c;BIO&#xff08;Blocking I/O&#xff09;、NIO&#xff08;Non-blocking I/O&#xff09;和 AIO&#xff08;Asynchronous I/O&#xff09;是三种不同的 I/O 模型&#xff0c;它们在处理输入输出操作时有着不同的机制和特点&#xff0c;但是市…

    使用(xshell+xftp)将前端项目部署到服务器

    一.以vue项目为例 将项目打包生成dist文件 二.下载载安装xshell和xftp 下载地址&#xff1a;家庭/学校免费 - NetSarang Website 三.连接服务器 在xshell新建会话&#xff08;需要用到服务器、用户名、密码、端口号&#xff09;正确输入后连接到服务器 使用命令连接&#x…

    硬件岗位是否适合你?

    在当今科技飞速发展的时代,硬件行业作为技术创新的基石,始终扮演着至关重要的角色。无论是智能手机、自动驾驶汽车,还是人工智能服务器,硬件都是这些技术的核心支撑。然而,硬件岗位是否适合你?作为一名硬件专家,我将从多个角度为你分析,帮助你判断自己是否适合从事硬件…

    Linux基本指令(二)

    文章目录 基本指令echocat&#xff08;输入重定向&#xff09;history日志moretail和headmv&#xff08;重要&#xff09;时间相关的指令查找的命令 知识点Linux下一切皆文件为什么计算机关机了&#xff0c;开机后还能准确地记录时间呢&#xff1f; 基本指令 echo 1. echo&…

    【Blender】二、建模篇--05,阵列修改器与晶格形变

    阵列修改器是bender里面一个比较常用的修改器,所以我们单独开口来讲,我们会先从几片树叶出发,然后我们用阵列修改器把这几片树叶变成这样的造型和这样的造型。这两个造型分别就代表着阵列修改器最常用的两种偏移方法,我们现在就开始我们先来做几个树叶。 1.树叶建模 首先…

    fpga助教面试题

    第一题 module sfp_pwm( input wire clk, //clk is 200M input wire rst_n, input wire clk_10M_i, input wire PPS_i, output reg pwm ) reg [6:0] cunt ;always (posedge clk ) beginif(!rst_n)cunt<0;else if(cunt19) //200M是10M的20倍cunt<0;elsecunt<cunt1;…