当前位置:首页 > 综合资讯 > 正文
黑狐家游戏

java中的集合类可以用来存储任何类型的对象,集合存储的对象必须是基本数据类型

java中的集合类可以用来存储任何类型的对象,集合存储的对象必须是基本数据类型

《Java集合:存储对象类型的多样性》在Java编程中,集合类是非常重要的一部分,与标题中所说的“集合存储的对象必须是基本数据类型”相反,Java中的集合类具有强大的功...

本文目录导读:

java中的集合类可以用来存储任何类型的对象,集合存储的对象必须是基本数据类型

  1. Java集合框架概述
  2. 存储自定义对象
  3. 存储基本数据类型的包装类
  4. 集合操作中的类型安全性
  5. 集合遍历与对象操作
  6. 集合与多态
  7. 集合的序列化与存储对象
  8. 集合存储对象的性能考虑

《Java集合:存储对象类型的多样性》

在Java编程中,集合类是非常重要的一部分,与标题中所说的“集合存储的对象必须是基本数据类型”相反,Java中的集合类具有强大的功能,可以用来存储任何类型的对象,包括自定义的类对象、基本数据类型的包装类对象等,这一特性使得集合在各种Java应用程序中得到广泛的应用,从简单的数据管理到复杂的企业级系统开发。

Java集合框架概述

(一)集合框架的层次结构

Java集合框架主要包含两大接口分支:CollectionMap

1、Collection接口

Collection是所有集合类的根接口,它定义了一些基本的操作,如添加、删除、遍历元素等。Collection接口有三个主要的子接口:ListSetQueue

List接口

List是一个有序的集合,允许元素重复。ArrayListLinkedListList接口的两个常见实现类。ArrayList基于数组实现,具有快速的随机访问特性,适合频繁读取元素的场景,而LinkedList基于链表实现,在插入和删除操作上具有较高的效率,特别是在列表的头部或尾部进行操作时。

Set接口

Set是一个不允许元素重复的集合。HashSetSet接口最常用的实现类之一,它基于哈希表实现,能够快速地查找元素。TreeSet则是基于红黑树实现的Set,它会对元素进行排序,适合需要对元素进行有序存储和检索的场景。

Queue接口

Queue用于处理按特定顺序排队的元素,例如LinkedList也可以作为Queue来使用。PriorityQueue是一种特殊的队列,它会根据元素的优先级对元素进行排序,优先级高的元素会先出队。

2、Map接口

Map用于存储键 - 值对,其中键是唯一的。HashMapMap接口最常用的实现类,它基于哈希表实现,提供了快速的查找、插入和删除操作。TreeMap则是基于红黑树实现的Map,会根据键对键 - 值对进行排序。

(二)集合类存储对象的基本原理

1、对象引用的存储

- 当把一个对象存储到集合中时,实际上存储的是对象的引用,在ArrayList中,内部维护了一个对象引用的数组,当我们执行list.add(new MyObject())(假设MyObject是一个自定义类)时,new MyObject()创建的对象在堆内存中,而ArrayList只是存储了指向这个对象的引用。

2、内存管理与对象生命周期

- 集合中的对象生命周期与集合本身的生命周期以及Java的垃圾回收机制密切相关,如果一个对象只被集合中的引用所指向,并且当集合不再引用这个对象时(例如从集合中删除了这个对象的引用),这个对象就有可能被垃圾回收器回收。

存储自定义对象

1、自定义类的定义

- 假设我们定义了一个简单的Person类:

```java

class Person {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

}

```

2、将自定义对象存储到集合中

- 我们可以将Person对象存储到List中:

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<Person> personList = new ArrayList<>();

personList.add(new Person("Alice", 25));

personList.add(new Person("Bob", 30));

for (Person person : personList) {

System.out.println(person.getName() + " " + person.getAge());

}

}

}

```

- 同样,也可以将Person对象存储到Set中,如果我们使用HashSet,需要注意自定义类要正确重写hashCode()equals()方法,以确保对象的唯一性判断正确。

```java

class Person {

//...

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass()!= o.getClass()) return false;

Person person = (Person) o;

return age == person.age && Objects.equals(name, person.name);

}

@Override

public int hashCode() {

return Objects.hash(name, age);

}

}

public class Main {

public static void main(String[] args) {

Set<Person> personSet = new HashSet<>();

personSet.add(new Person("Alice", 25));

personSet.add(new Person("Bob", 30));

personSet.add(new Person("Alice", 25));//这个对象不会被重复添加

for (Person person : personSet) {

System.out.println(person.getName() + " " + person.getAge());

}

}

}

```

存储基本数据类型的包装类

1、基本数据类型包装类简介

- 在Java中,基本数据类型(如intdoubleboolean等)有对应的包装类(IntegerDoubleBoolean等),这些包装类使得基本数据类型可以像对象一样被处理,从而可以存储在集合中。

2、存储包装类对象到集合中

- 我们可以将Integer对象存储到List中:

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<Integer> integerList = new ArrayList<>();

integerList.add(Integer.valueOf(1));

integerList.add(Integer.valueOf(2));

for (Integer num : integerList) {

System.out.println(num);

}

}

}

```

- 在Java 5及以后版本中,由于自动装箱和自动拆箱机制的引入,我们可以直接将基本数据类型赋值给包装类类型的变量或者将包装类对象赋值给基本数据类型变量,这使得在集合中使用基本数据类型的包装类更加方便。

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<Integer> integerList = new ArrayList<>();

integerList.add(1);

integerList.add(2);

java中的集合类可以用来存储任何类型的对象,集合存储的对象必须是基本数据类型

int num = integerList.get(0);

System.out.println(num);

}

}

```

集合操作中的类型安全性

1、泛型与类型安全

- Java中的泛型为集合提供了类型安全的保障,通过在定义集合时指定元素的类型,如List<String>表示这个List只能存储String类型的对象,这样可以在编译时发现类型不匹配的错误,避免在运行时出现ClassCastException等异常。

- 如果我们试图将一个Integer对象添加到List<String>中,在编译时就会报错:

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<String> stringList = new ArrayList<>();

stringList.add("Hello");

//stringList.add(Integer.valueOf(1));//编译错误

}

}

```

2、类型擦除与运行时类型检查

- 虽然Java在编译时使用泛型进行类型检查,但在运行时会发生类型擦除,这意味着在运行时,集合中的对象类型信息会被部分擦除,不过,Java仍然会进行一些必要的运行时类型检查,例如在进行强制类型转换时,如果对象的实际类型与转换的目标类型不匹配,就会抛出ClassCastException

集合遍历与对象操作

1、遍历集合中的对象

- 对于ListSetCollection类型的集合,我们可以使用for - each循环或者迭代器(Iterator)来遍历集合中的对象。

- 使用for - each循环:

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<String> stringList = new ArrayList<>();

stringList.add("Apple");

stringList.add("Banana");

for (String fruit : stringList) {

System.out.println(fruit);

}

}

}

```

- 使用迭代器:

```java

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<String> stringList = new ArrayList<>();

stringList.add("Apple");

stringList.add("Banana");

Iterator<String> iterator = stringList.iterator();

while (iterator.hasNext()) {

String fruit = iterator.next();

System.out.println(fruit);

}

}

}

```

2、在遍历过程中操作对象

- 在遍历集合中的对象时,我们可以对对象进行各种操作,如修改对象的属性(对于可变对象)或者根据某些条件删除对象,对于一个存储Person对象的List,我们可以修改年龄属性:

```java

import java.util.ArrayList;

import java.util.List;

class Person {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

public class Main {

public static void main(String[] args) {

List<Person> personList = new ArrayList<>();

personList.add(new Person("Alice", 25));

personList.add(new Person("Bob", 30));

for (Person person : personList) {

if (person.getName().equals("Alice")) {

person.setAge(26);

}

}

for (Person person : personList) {

System.out.println(person.getName() + " " + person.getAge());

}

}

}

```

集合与多态

1、多态在集合中的体现

- 当我们将不同类型的对象存储到集合中时,多态性得到了很好的体现,我们定义了一个Animal接口,以及DogCat两个实现类:

```java

interface Animal {

void makeSound();

}

class Dog implements Animal {

@Override

public void makeSound() {

System.out.println("Woof!");

}

}

class Cat implements Animal {

@Override

java中的集合类可以用来存储任何类型的对象,集合存储的对象必须是基本数据类型

public void makeSound() {

System.out.println("Meow!");

}

}

```

- 我们可以将DogCat对象存储到一个List<Animal>中:

```java

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List<Animal> animalList = new ArrayList<>();

animalList.add(new Dog());

animalList.add(new Cat());

for (Animal animal : animalList) {

animal.makeSound();

}

}

}

```

2、利用多态进行通用的集合操作

- 通过多态,我们可以编写更通用的代码来处理集合中的对象,我们可以定义一个方法来处理List<Animal>中的所有动物对象,而不需要为每个具体的动物类编写单独的方法:

```java

public class Main {

public static void handleAnimals(List<Animal> animalList) {

for (Animal animal : animalList) {

animal.makeSound();

}

}

public static void main(String[] args) {

List<Animal> animalList = new ArrayList<>();

animalList.add(new Dog());

animalList.add(new Cat());

handleAnimals(animalList);

}

}

```

集合的序列化与存储对象

1、对象序列化简介

- 对象序列化是将对象转换为字节流的过程,这样可以将对象存储到文件或者在网络上传输,对于集合中的对象,如果要进行序列化,集合中的对象类必须实现Serializable接口。

2、序列化集合中的对象

- 我们将一个存储Person对象的ArrayList序列化到文件中:

```java

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

import java.util.List;

class Person implements Serializable {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

//...

}

public class Main {

public static void main(String[] args) {

List<Person> personList = new ArrayList<>();

personList.add(new Person("Alice", 25));

personList.add(new Person("Bob", 30));

try {

FileOutputStream fileOut = new FileOutputStream("person.ser");

ObjectOutputStream out = new ObjectOutputStream(fileOut);

out.writeObject(personList);

out.close();

fileOut.close();

System.out.println("Serialized data is saved in person.ser");

} catch (IOException e) {

e.printStackTrace();

}

}

}

```

- 然后可以从文件中反序列化这个集合:

```java

import java.io.FileInputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.util.List;

public class Main {

public static void main(String[] args) {

try {

FileInputStream fileIn = new FileInputStream("person.ser");

ObjectInputStream in = new ObjectInputStream(fileIn);

List<Person> personList = (List<Person>) in.readObject();

in.close();

fileIn.close();

for (Person person : personList) {

System.out.println(person.getName() + " " + person.getAge());

}

} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();

}

}

}

```

集合存储对象的性能考虑

1、不同集合类型的性能特点

ArrayList:在随机访问元素时性能非常好,时间复杂度为$O(1)$,但是在插入和删除元素时,尤其是在列表中间进行操作时,性能较差,因为需要移动大量的元素,插入和删除操作的平均时间复杂度为$O(n)$。

LinkedList:在插入和删除元素时,特别是在头部或尾部操作时性能较好,时间复杂度为$O(1)$,但是随机访问元素的性能较差,时间复杂度为$O(n)$。

HashSet:添加、删除和查找元素的时间复杂度接近常数时间$O(1)$,但是需要注意哈希冲突的处理。

TreeSet:查找、插入和删除操作的时间复杂度为$O(log n)$,由于需要维护元素的排序,性能相对HashSet在某些操作上可能会稍慢一些。

2、选择合适的集合类型存储对象

- 如果需要频繁地随机访问元素,并且元素的数量相对固定或者插入删除操作较少,ArrayList是一个较好的选择,如果经常需要在头部或尾部插入或删除元素,LinkedList更合适,如果要确保元素的唯一性并且对查找速度要求较高,HashSet是首选,而如果还需要对元素进行排序,TreeSet则是更好的选择,对于键 - 值对的存储,如果不要求排序,HashMap性能较好,要求排序则选择TreeMap

Java中的集合类具有很强的灵活性,可以存储任何类型的对象,包括自定义类对象和基本数据类型的包装类对象,通过合理地利用集合类的特性,如泛型保证类型安全、多态实现通用操作、序列化进行对象存储等,以及根据性能需求选择合适的集合类型,我们可以高效地管理和操作各种对象,这种对象存储的多样性使得集合类成为Java编程中不可或缺的一部分,广泛应用于从简单的桌面应用到复杂的企业级系统等各种场景中。

黑狐家游戏

发表评论

最新文章