如何用 Java 漂亮地列印地圖
一、簡介
在 Java 中美化列印Map
涉及以視覺上有吸引力且可讀的方式格式化和顯示地圖的鍵值對。雖然 Java 沒有提供用於漂亮列印地圖的內建方法,但我們必須實作自訂解決方案。
在本教程中,我們將學習如何實現這一目標。根據我們的偏好和詳細程度,我們將探索多種方法,僅使用標準 JDK,然後使用外部函式庫。
2. 創建Map
在繼續之前,讓我們先建立一個要使用的地圖:
Map<String, Object> map = Map.of(
"one", 1,
"two", 2,
"inner", Map.of(
"ten", 10,
"eleven", 11
)
);
值得注意的是,我們透過添加內部巢狀映射來擴展我們的範例。
3. 使用核心Java
眾所周知,Java 可以使用內建的toString()
方法列印地圖:
{one=1, two=2, inner={eleven=11, ten=10}}
輸出以簡單的方式預先格式化,並在一行上顯示以逗號分隔的鍵值對。它適用於簡單的地圖或調試期間。
但如果我們想要一張列印漂亮的地圖,我們就必須實作自訂方法。
3.1.使用for
-each 循環
當我們需要迭代所有元素時,我們可以使用for
-each 循環:
for (Map.Entry<?, ?> entry : map.entrySet()) {
System.out.printf("%-15s : %s%n", entry.getKey(), entry.getValue());
}
該循環將列印:
one : 1
two : 2
inner : {ten=10, eleven=11}
現在輸出看起來更好了,但是我們的內部地圖仍然沒有印得很漂亮,所以我們必須手動處理複雜的結構。
為了格式化我們的內部條目,讓我們實作一個帶有遞歸和左填充參數化的輔助函數:
void printMap(int leftPadding, Map<?, ?> map) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
System.out.printf("%-15s :%n", entry.getKey());
printMap(leftPadding + 4, (Map<?, ?>) entry.getValue());
}
else {
System.out.printf("%" + (leftPadding > 0 ? leftPadding : "") + "s" // adding padding
+ "%-15s : %s%n",
"", entry.getKey(), entry.getValue());
}
}
}
現在,如果我們透過呼叫printMap(0, map)
來執行該方法,它將列印:
one : 1
two : 2
inner :
ten : 10
eleven : 11
透過實施我們的自訂解決方案,我們在列印地圖時始終擁有完全的控制權。我們可以使用內建格式化程式(例如Formatter class
、 String.format()
甚至System.out.printf()
來自訂輸出。另一方面,如果我們想處理多種類型或內部結構,自訂函數可能會有點複雜。
3.2.使用Stream
在 Java 中,我們幾乎可以用Stream
取代任何for
-each 迴圈。我們可以使用一行來列印和格式化我們的地圖:
map.forEach((k, v) -> System.out.printf("%-15s : %s%n", k, v));
如果我們想要更多控制,我們可以擴展流並使用map()
或Collectors.joining()
函數:
System.out.println(MAP.entrySet().stream()
.map(entry -> String.format("%-15s : %s", entry.getKey(), entry.getValue()))
.collect(Collectors.joining("\n")));
在這兩個例子中,我們都會得到:
one : 1
two : 2
inner : {ten=10, eleven=11}
再一次,這種方法使我們能夠更好地控制格式,並且非常適合簡單類型。我們必須記住手動處理任何複雜的結構,就像我們之前所做的那樣。
4. 外部庫
如果我們沒有複雜的地圖,那麼實現自訂的漂亮列印功能可能是個不錯的選擇。任何額外的映射都會使我們的程式碼更加複雜且不值得實現。讓我們來看看外部函式庫提供的解決方案。
4.1.傑克森
如果我們比較 JSON 和 Map,我們可以發現很多相似之處。在這兩種情況下,鍵值對都用於表示條目。
首先,讓我們檢查Jackson ,這是最受歡迎的 JSON 庫之一,將其依賴項包含在我們的pom.xml
中:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.1</version>
</dependency>
Jackson 提供了一個ObjectMapper
類,它不僅可以用來處理 JSON,還可以用於標準地圖:
String json = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(map);
結果,Jackson API 漂亮地列印了我們的地圖:
{
"one" : 1,
"two" : 2,
"inner" : {
"ten" : 10,
"eleven" : 11
}
}
該解決方案自動處理我們的內部地圖,並且比以前的解決方案簡單得多。不幸的是,我們無法完全控制映射。
4.2.格森
當然,其他 JSON 庫也支援漂亮列印的地圖。讓我們透過新增最新版本的依賴項來檢查 Gson:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
就像我們之前所做的一樣,讓我們設定一個GsonBuilder
:
String json = new GsonBuilder().setPrettyPrinting().create().toJson(MAP);
現在的結果是這樣的:
{
"one": 1,
"two": 2,
"inner": {
"ten": 10,
"eleven": 11
}
}
值得注意的是,我們的格式略有不同(鍵後沒有空格),但同樣,漂亮列印支援嵌套值的地圖**要容易得多**。
4.3. Apache 共享集合
當我們知道 JSON 庫通常支援 JSON 和用於漂亮列印的映射時,讓我們探索非 JSON 庫提供的其他解決方案。
讓我們透過向專案新增依賴項來查看Apache Commons Collections :
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
該函式庫為我們帶來了MapUtils
類別。讓我們用它來列印我們的地圖:
MapUtils.debugPrint(System.out, "map", map);
結果,我們將得到如下格式的地圖:
map =
{
one = 1 java.lang.Integer
two = 2 java.lang.Integer
inner =
{
ten = 10 java.lang.Integer
eleven = 11 java.lang.Integer
} java.util.HashMap
} java.util.HashMap
我們剛剛使用debugPrint()
方法來格式化地圖。如果我們想要省略值的類別名,我們可以使用verbosePrint()
。
4.4.谷歌番石榴
最後,我們來看看Google Guava 庫提供的方法。在開始之前,讓我們先更新pom.xml
:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.0.0-jre</version>
</dependency>
要列印地圖,我們可以使用Joiner類別:
String mapStr = Joiner.on(",\n").withKeyValueSeparator("=").join(map);
如果我們現在檢查結果,我們將得到:
one=1,
two=2,
inner={ten=10, eleven=11}
不幸的是,這種方法無法處理巢狀條目,但它適用於單層結構。
5. 結論
在本文中,我們學習了用 Java 列印精美地圖的不同方法。眾所周知,使用內建的toString()
方法列印可能會導致不可讀的單行字串。
我們首先使用標準 Java API實作自訂漂亮列印方法,特別是for
-each 循環、流和格式化程式。如果我們有簡單的非巢狀映射**或想要完全控制映射**,那麼這種方法適合我們。
之後,我們檢查了 Jackson、Gson、Apache Commons Collections 或 Guava 等外部函式庫提供的解決方案。外部 API 總是比實作自訂解決方案更簡單,但我們對預訂列印格式的控制較少。
與往常一樣,本文隨附的源代碼可以在 GitHub 上找到。