打印出 List<Product> 中的内容

本文介绍了几种遍历Java List集合的方法,包括for循环、foreach增强循环及迭代器方式,并展示了如何使用不同包来解析JSON数据。

List<Product>

List 中放的是一个Product类,包含Name,NO



public static void main(String[] args) {
        List<Product> prods = new ArrayList<Product>();
        
        // 1. 使用 for
        Product prod = null;
        for (int i = 0; i < prods.size(); i++) {
            prod = prods.get(i);
            System.out.println(prod.getName() + prod.getNo());
        }
        
        // 2. 使用 foreach
        for (Product p : prods) {
            System.out.println(p.getName() + p.getNo()); 
        }

        // 3. 使用迭代器
        Iterator<Product> iter = null;
        for (iter = prods.iterator(); iter.hasNext(); ) {
            prod = iter.next();
            System.out.println(prod.getName() + prod.getNo());
        }

    }


Json 数据打印

 JSONObject jsonObject = JSONObject.fromObject(json);

 Set set = jsonObject.keySet();
 for (Object key : set){
   System.out.println(key);
 }

需要引入的包
commons-beanutils-1.8.3
commons-collections-3.2.1
ezmorph-1.0.5

引入net.sf.json.JSONObject  

        JSONObject object = JSONObject.fromObject(jsonData);


引入org.json.JSONObject

       JSONObject object = new JSONObject(jsonData);





<think> 我们需要处理一个Map<String, List<MetaColumn>>,其中每个key对应的List<MetaColumn>中可能包含重复的MetaColumn对象。我们需要根据MetaColumn对象的某些字段(比如列名和类型)去重,保留一个(例如第一个现的)重复项。 假设MetaColumn类有getName()和getType()方法,我们根据这两个字段组合去重。如果还有其他字段需要参与去重,可以类似处理。 处理思路: 1. 遍历Map的每个键(key)。 2. 对每个key对应的List<MetaColumn>进行去重操作,去重规则:如果两个MetaColumn的name和type相同,则认为重复。 3. 去重时保留第一个现的元素。 我们可以使用Stream API的distinct()方法,但distinct()依赖于对象的equals()和hashCode()。如果我们不能修改MetaColumn类的equals和hashCode方法,就需要使用其他方式。 另一种方式是使用Collectors.toMap()或Collectors.collectingAndThen()来模拟去重,类似于之前对List<MetaTable>的去重。 以下是具体步骤: 方案:对Map中的每个List<MetaColumn>进行去重,然后重新组装Map。 代码示例: 假设MetaColumn类如下: ```java class MetaColumn { private String name; private String type; public MetaColumn(String name, String type) { this.name = name; this.type = type; } public String getName() { return name; } public String getType() { return type; } // 其他字段和方法省略 } ``` 去重操作代码: ```java Map<String, List<MetaColumn>> distinctColumnsMap = new HashMap<>(); for (Map.Entry<String, List<MetaColumn>> entry : columns.entrySet()) { String key = entry.getKey(); List<MetaColumn> columnList = entry.getValue(); // 使用Stream去重:根据name和type组合去重,保留第一次现的 List<MetaColumn> distinctList = columnList.stream() .collect(Collectors.collectingAndThen( Collectors.toMap( column -> column.getName() + "|" + column.getType(), // 组合键 Function.identity(), (existing, replacement) -> existing, // 保留已存在的(第一次现) LinkedHashMap::new ), map -> new ArrayList<>(map.values()) )); distinctColumnsMap.put(key, distinctList); } ``` 如果我们希望保留最后一次现的元素,只需要将`(existing, replacement) -> existing`改为`(existing, replacement) -> replacement`。 但是,请注意:如果去重字段不止两个,我们可以使用一个对象作为键(例如一个内部类或者一个字符串连接,但要确保连接符不会现在字段中),或者使用Java的Record(Java 14+)或Pair类(如果可用)。这里我们使用字符串连接,但要注意分隔符的选择。 改进:使用不可见字符或更复杂的组合键避免冲突。 另一种方式是使用自定义的key对象,但由于是在方法内部,我们可以定义一个Tuple类(或者使用AbstractMap.SimpleEntry)作为键。例如: ```java List<MetaColumn> distinctList = columnList.stream() .collect(Collectors.collectingAndThen( Collectors.toMap( column -> Arrays.asList(column.getName(), column.getType()), // 使用List作为复合键 Function.identity(), (existing, replacement) -> existing, LinkedHashMap::new ), map -> new ArrayList<>(map.values()) )); ``` 但是,这样做的缺点是List是可变对象,且没有重写equals和hashCode(实际上List重写了,所以可以作为键)。不过,使用List作为键在逻辑上是可行的,因为List的equals和hashCode是基于内容的。 不过,在Map中使用List作为键可能不是最佳实践,因为List是可变的,但在这个临时Map中不会有问题。 我们也可以使用一个字符串连接,但为了避免字段值中包含分隔符而导致冲突,我们可以使用一个不常见的分隔符(如Unicode字符)或者使用hashCode(但hashCode可能有冲突,不推荐)。 更稳妥的方法是使用一个不可变对象作为键,例如Java 9+的Map.entry(但注意Map.entry是不可变的,但作为键需要放入Map中,而Map的键应该是不可变的,所以可以): ```java List<MetaColumn> distinctList = columnList.stream() .collect(Collectors.collectingAndThen( Collectors.toMap( column -> Map.entry(column.getName(), column.getType()), Function.identity(), (existing, replacement) -> existing, LinkedHashMap::new ), map -> new ArrayList<>(map.values()) )); ``` 这个方法使用了Map.entry作为键,因为Map.entry重写了equals和hashCode,所以可以正确比较。 但是请注意:Map.entry是不可变的,所以作为键是安全的。 总结:我们遍历原始Map的每个键,对每个键对应的List使用复合键去重,然后放入新的Map中。 完整示例代码: ```java import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; public class MapColumnDistinct { public static void main(String[] args) { // 示例数据:构建一个Map<String, List<MetaColumn>> Map<String, List<MetaColumn>> columns = new HashMap<>(); columns.put("table1", Arrays.asList( new MetaColumn("id", "int"), new MetaColumn("name", "varchar"), new MetaColumn("id", "int"), // 重复 new MetaColumn("name", "varchar(50)") // 不重复,因为type不同 )); columns.put("table2", Arrays.asList( new MetaColumn("id", "int"), new MetaColumn("id", "int") // 重复 )); // 调用去重方法 Map<String, List<MetaColumn>> distinctColumnsMap = distinctColumnsByKey(columns); // 输结果 distinctColumnsMap.forEach((key, list) -> { System.out.println("Table: " + key); list.forEach(col -> System.out.println(" " + col.getName() + ": " + col.getType())); }); } public static Map<String, List<MetaColumn>> distinctColumnsByKey(Map<String, List<MetaColumn>> columns) { Map<String, List<MetaColumn>> distinctMap = new HashMap<>(); for (Map.Entry<String, List<MetaColumn>> entry : columns.entrySet()) { // 对每个List<MetaColumn>去重 List<MetaColumn> distinctList = entry.getValue().stream() .collect(Collectors.collectingAndThen( Collectors.toMap( column -> Map.entry(column.getName(), column.getType()), Function.identity(), (existing, replacement) -> existing, // 保留第一个 LinkedHashMap::new ), map -> new ArrayList<>(map.values()) )); distinctMap.put(entry.getKey(), distinctList); } return distinctMap; } static class MetaColumn { private String name; private String type; public MetaColumn(String name, String type) { this.name = name; this.type = type; } public String getName() { return name; } public String getType() { return type; } } } ``` 输: ``` Table: table1 id: int name: varchar name: varchar(50) Table: table2 id: int ``` 注意:在table1中,重复的"id:int"被去除了,而"name:varchar"和"name:varchar(50)"被视为不同(因为type不同),所以都保留。 §§相关问题§§: 1. 如果去重规则需要根据MetaColumn的更多字段(例如三个字段)来确定唯一性,代码该如何修改? 2. 在去重时,如果想保留最后一次现的MetaColumn而不是第一次,代码该如何调整? 3. 这种去重方式的时间复杂度和空间复杂度是多少? 4. 如果Map中某个key对应的List非常大,如何优化去重性能? </think> # 处理 Map<String, List<MetaColumn>> 的去重问题 针对 `Map<String, List<MetaColumn>>` 的去重需求(每个 key 对应的 List 内部去重),以下是完整的解决方案: ```java import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; public class MetaColumnDistinct { public static void main(String[] args) { // 示例数据 Map<String, List<MetaColumn>> columns = new HashMap<>(); columns.put("table1", Arrays.asList( new MetaColumn("id", "INT"), new MetaColumn("name", "VARCHAR(50)"), new MetaColumn("id", "INT"), // 重复项 new MetaColumn("email", "VARCHAR(100)") )); columns.put("table2", Arrays.asList( new MetaColumn("product_id", "INT"), new MetaColumn("price", "DECIMAL(10,2)"), new MetaColumn("price", "DECIMAL(10,2)"), // 重复项 new MetaColumn("product_id", "BIGINT") // 不重复(类型不同) )); // 处理去重 Map<String, List<MetaColumn>> distinctColumns = distinctColumnsByKey(columns); // 打印结果 distinctColumns.forEach((key, list) -> { System.out.println("Table: " + key); list.forEach(col -> System.out.println(" " + col.getName() + ": " + col.getType())); System.out.println(); }); } /** * 对Map中每个key对应的List<MetaColumn>进行去重 * @param columns 原始数据 * @return 去重后的Map */ public static Map<String, List<MetaColumn>> distinctColumnsByKey(Map<String, List<MetaColumn>> columns) { Map<String, List<MetaColumn>> result = new HashMap<>(); for (Map.Entry<String, List<MetaColumn>> entry : columns.entrySet()) { String key = entry.getKey(); List<MetaColumn> originList = entry.getValue(); // 使用复合键去重:列名 + 类型 List<MetaColumn> distinctList = originList.stream() .collect(Collectors.collectingAndThen( Collectors.toMap( col -> col.getName() + "|" + col.getType(), // 复合键 Function.identity(), // 值=元素本身 (existing, replacement) -> existing, // 保留已存在的(第一次现) LinkedHashMap::new // 保持顺序 ), map -> new ArrayList<>(map.values()) // 转回List )); result.put(key, distinctList); } return result; } // MetaColumn 类示例 static class MetaColumn { private final String name; private final String type; public MetaColumn(String name, String type) { this.name = name; this.type = type; } public String getName() { return name; } public String getType() { return type; } } } ``` ## 代码解释 ### 1. 核心方法:`distinctColumnsByKey` ```java public static Map<String, List<MetaColumn>> distinctColumnsByKey(Map<String, List<MetaColumn>> columns) { Map<String, List<MetaColumn>> result = new HashMap<>(); for (Map.Entry<String, List<MetaColumn>> entry : columns.entrySet()) { // 获取原始键值对 String key = entry.getKey(); List<MetaColumn> originList = entry.getValue(); // 使用复合键去重 List<MetaColumn> distinctList = originList.stream() .collect(Collectors.collectingAndThen( Collectors.toMap( col -> col.getName() + "|" + col.getType(), // 复合键 Function.identity(), // 值=元素本身 (existing, replacement) -> existing, // 保留已存在的 LinkedHashMap::new // 保持顺序 ), map -> new ArrayList<>(map.values()) // 转回List )); result.put(key, distinctList); } return result; } ``` ### 2. 去重逻辑详解 - **复合键构造**:`col.getName() + "|" + col.getType()` 使用列名 + 类型作为唯一标识符,确保相同列名但不同类型不被视为重复 - **键冲突处理**:`(existing, replacement) -> existing` 保留首次现的元素(修改为`(e, r) -> r`可保留最后一次现的元素) - **顺序保持**:`LinkedHashMap::new` 保持原始List中元素的插入顺序 ### 3. 示例输 ``` Table: table1 id: INT name: VARCHAR(50) email: VARCHAR(100) Table: table2 product_id: INT price: DECIMAL(10,2) product_id: BIGINT ``` ## 常见场景处理 ### 1. 保留最后一次现而非第一次 ```java // 修改键冲突处理部分 (existing, replacement) -> replacement // 保留最后一次现的元素 ``` ### 2. 处理可能包含分隔符的字段值 ```java // 使用不可见字符作为分隔符 col -> col.getName() + "\u0000" + col.getType() // 或使用JSON格式 col -> String.format("{\"name\":\"%s\",\"type\":\"%s\"}", col.getName(), col.getType()) ``` ### 3. 使用字段对象代替字符串拼接(推荐) ```java // 定义记录字段的键对象 record ColumnKey(String name, String type) {} // 使用 .collect(Collectors.toMap( col -> new ColumnKey(col.getName(), col.getType()), Function.identity(), (existing, replacement) -> existing, LinkedHashMap::new )) ``` ### 4. Java 16+ 的简化写法(使用toList) ```java List<MetaColumn> distinctList = originList.stream() .distinct() // 需要重写MetaColumn的equals和hashCode方法 .toList(); ``` ## 最佳实践建议 1. **封装复合键逻辑**:创建专用的Key类(如`ColumnKey`)代替字符串拼接 2. **处理空值**:确保`getName()`和`getType()`方法能正确处理null值 3. **自定义对象**:让`MetaColumn`重写`equals()`和`hashCode()`方法 4. **并行处理**:对于大型数据集可使用并行流提高性能 5. **去重统计**:添加计数器记录移除的重复项数量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值