打印数组
大约 6 分钟
打印数组
概述
在Java开发中,数组打印是日常调试和数据展示的常见需求。由于数组直接打印会输出内存地址而非实际内容,掌握正确的数组打印方法对开发效率至关重要。本章将系统介绍Java中打印数组的多种方式,包括基础循环打印、工具类打印、流打印等方法,并分析各种方法的适用场景和性能特点。
知识要点
2.1 基础循环打印法
循环打印是最原始但最灵活的数组打印方式,适用于所有数组类型,尤其适合需要自定义格式的场景。
2.1.1 for循环打印一维数组
public class ArrayPrintDemo {
public static void printArrayWithForLoop() {
int[] numbers = {1, 2, 3, 4, 5};
System.out.print("[");
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i]);
if (i < numbers.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
// 输出: [1, 2, 3, 4, 5]
}
}2.1.2 增强for循环打印数组
public class ArrayPrintDemo {
public static void printArrayWithEnhancedFor() {
String[] fruits = {"Apple", "Banana", "Orange"};
System.out.print("[");
boolean first = true;
for (String fruit : fruits) {
if (!first) {
System.out.print(", ");
}
System.out.print(fruit);
first = false;
}
System.out.println("]");
// 输出: [Apple, Banana, Orange]
}
}2.1.3 嵌套循环打印二维数组
public class ArrayPrintDemo {
public static void print2DArrayWithLoop() {
int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
System.out.println("[");
for (int i = 0; i < matrix.length; i++) {
System.out.print(" [");
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j]);
if (j < matrix[i].length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
System.out.println("]");
/* 输出:
[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]
*/
}
}2.2 Arrays工具类打印法
Java提供了java.util.Arrays工具类,封装了常用的数组操作方法,其中toString()和deepToString()是打印数组的便捷工具。
2.2.1 Arrays.toString()打印一维数组
import java.util.Arrays;
public class ArrayPrintDemo {
public static void printWithArraysToString() {
int[] numbers = {1, 2, 3, 4, 5};
String[] fruits = {"Apple", "Banana", "Orange"};
double[] prices = {10.99, 20.50, 5.99};
System.out.println(Arrays.toString(numbers)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(fruits)); // [Apple, Banana, Orange]
System.out.println(Arrays.toString(prices)); // [10.99, 20.5, 5.99]
}
}2.2.2 Arrays.deepToString()打印多维数组
import java.util.Arrays;
public class ArrayPrintDemo {
public static void printWithArraysDeepToString() {
int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
String[][] names = { {"Alice", "Bob"}, {"Charlie", "David"} };
System.out.println(Arrays.deepToString(matrix)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
System.out.println(Arrays.deepToString(names)); // [[Alice, Bob], [Charlie, David]]
}
}2.2.3 Arrays.asList()配合打印
import java.util.Arrays;
public class ArrayPrintDemo {
public static void printWithArraysAsList() {
String[] fruits = {"Apple", "Banana", "Orange"};
// Arrays.asList()将数组转换为List集合
System.out.println(Arrays.asList(fruits)); // [Apple, Banana, Orange]
}
}2.3 Java 8+流API打印法
Java 8引入的Stream API提供了更现代、更灵活的数组打印方式,支持函数式编程风格。
2.3.1 使用Stream.forEach()打印
import java.util.Arrays;
public class ArrayPrintDemo {
public static void printWithStreamForEach() {
int[] numbers = {1, 2, 3, 4, 5};
String[] fruits = {"Apple", "Banana", "Orange"};
// 打印int数组
System.out.print("[");
Arrays.stream(numbers).forEach(n -> System.out.print(n + ", "));
System.out.println("]"); // [1, 2, 3, 4, 5, ]
// 打印String数组
System.out.print("[");
Arrays.stream(fruits).forEach(f -> System.out.print(f + ", "));
System.out.println("]"); // [Apple, Banana, Orange, ]
}
}2.3.2 使用Collectors.joining()格式化打印
import java.util.Arrays;
import java.util.stream.Collectors;
public class ArrayPrintDemo {
public static void printWithCollectorsJoining() {
String[] fruits = {"Apple", "Banana", "Orange"};
// 使用Stream API和Collectors.joining()格式化
String result = Arrays.stream(fruits)
.collect(Collectors.joining(", ", "[", "]"));
System.out.println(result); // [Apple, Banana, Orange]
}
}2.4 常见数组类型打印对比
不同类型的数组需要采用不同的打印策略,以下是常见数组类型的最佳打印实践:
2.4.1 基本类型数组
import java.util.Arrays;
public class ArrayPrintDemo {
public static void printPrimitiveArrays() {
int[] intArray = {1, 2, 3};
char[] charArray = {'a', 'b', 'c'};
boolean[] boolArray = {true, false, true};
// 基本类型数组推荐使用Arrays.toString()
System.out.println(Arrays.toString(intArray)); // [1, 2, 3]
System.out.println(Arrays.toString(charArray)); // [a, b, c]
System.out.println(Arrays.toString(boolArray)); // [true, false, true]
}
}2.4.2 对象数组
import java.util.Arrays;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写toString()方法
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class ArrayPrintDemo {
public static void printObjectArrays() {
Person[] people = {
new Person("Alice", 25),
new Person("Bob", 30)
};
// 对象数组打印依赖于对象的toString()方法
System.out.println(Arrays.toString(people)); // [Alice(25), Bob(30)]
}
}知识扩展
3.1 设计思想
3.1.1 数组打印方法性能对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| for循环 | 完全自定义,无额外依赖 | 代码冗长,易出错 | 需要高度自定义格式 |
| Arrays.toString() | 简洁高效,代码量少 | 格式固定,无法自定义 | 快速打印,调试场景 |
| Stream API | 函数式风格,可链式操作 | JDK8+依赖,性能略低 | 复杂格式化,函数式编程 |
| 第三方库 | 功能丰富,使用简单 | 引入外部依赖 | 企业级项目,复杂需求 |
3.1.2 自定义数组打印工具类
import java.util.Arrays;
public class ArrayPrinter {
// 私有化构造方法,防止实例化
private ArrayPrinter() {}
// 打印一维数组
public static <T> void print(T[] array) {
if (array == null) {
System.out.println("null");
return;
}
System.out.println(Arrays.toString(array));
}
// 打印基本类型int数组
public static void print(int[] array) {
if (array == null) {
System.out.println("null");
return;
}
System.out.println(Arrays.toString(array));
}
// 打印多维数组
public static void print(Object[][] array) {
if (array == null) {
System.out.println("null");
return;
}
System.out.println(Arrays.deepToString(array));
}
// 自定义格式打印
public static <T> void printCustom(T[] array, String prefix, String suffix, String delimiter) {
if (array == null) {
System.out.println(prefix + suffix);
return;
}
StringBuilder sb = new StringBuilder(prefix);
for (int i = 0; i < array.length; i++) {
sb.append(array[i]);
if (i < array.length - 1) {
sb.append(delimiter);
}
}
sb.append(suffix);
System.out.println(sb.toString());
}
}3.2 避坑指南
3.2.1 直接打印数组引用的陷阱
问题:直接打印数组变量会输出内存地址而非内容 解决方案:使用Arrays.toString()或其他打印方法
int[] numbers = {1, 2, 3};
// 错误示例
System.out.println(numbers); // 输出类似: [I@1b6d3586
// 正确示例
System.out.println(Arrays.toString(numbers)); // [1, 2, 3]3.2.2 多维数组打印的问题
问题:使用Arrays.toString()打印多维数组无法正确显示嵌套内容 解决方案:使用Arrays.deepToString()方法
int[][] matrix = { {1, 2, 3}, {4, 5, 6} };
// 错误示例
System.out.println(Arrays.toString(matrix)); // [[I@4554617c, [I@74a14482]
// 正确示例
System.out.println(Arrays.deepToString(matrix)); // [[1, 2, 3], [4, 5, 6]]3.2.3 对象数组打印无意义内容
问题:对象数组打印时显示类似com.example.Person@123456解决方案:重写对象的toString()方法
class Person {
private String name;
private int age;
// 构造方法省略
// 重写toString()方法
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
// 打印结果将变为有意义的内容
// [Person{name='Alice', age=25}, Person{name='Bob', age=30}]3.3 深度思考题
- Arrays.toString()和Arrays.deepToString()的实现原理有何不同?
- 为什么基本类型数组和对象数组的打印方式需要区分对待?
- 如何实现一个通用的数组打印工具类,支持任意类型、任意维度的数组?
- 在大数据量数组打印时,如何避免内存溢出和性能问题?
思考题参考答案
Arrays.toString()与Arrays.deepToString()的实现区别:
- Arrays.toString():适用于一维数组,直接遍历数组元素并拼接字符串
- Arrays.deepToString():适用于多维数组,通过递归方式处理嵌套数组
- 源码核心区别在于deepToString()会检查元素是否为数组类型,如果是则递归调用
通用数组打印工具类实现思路:
public class UniversalArrayPrinter {
public static String toString(Object array) {
if (array == null) return "null";
if (!array.getClass().isArray()) return array.toString();
StringBuilder sb = new StringBuilder();
sb.append("[");
int length = java.lang.reflect.Array.getLength(array);
for (int i = 0; i < length; i++) {
Object element = java.lang.reflect.Array.get(array, i);
if (i > 0) sb.append(", ");
sb.append(toString(element)); // 递归处理
}
sb.append("]");
return sb.toString();
}
}