Java数据转换及属性获取

一、数据转换

(1)数据转换工具类

/**
 * 数据转换工具类
 * @author songwp
 */
public class DataUtils{
    /**
     * 定义分割常量
     * #用于list中每个元素间的分割
     * |用于map中每一个kv对间的分割
     * =用于map中key与value间的分割
     */
    private static final String SEP1 = ",";
    private static final String SEP2 = "|";
    private static final String SEP3 = "=";
    private static final String SEP4 = ";";

    /**
     * List转换String
     *
     * @param list            需要转换的List
     * @return String        转换后的字符串
     */
    public static String ListToString(List<?> list) {
        StringBuffer sb = new StringBuffer();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i) == null || list.get(i) == "") {
                    continue;
                }
                // 如果值是list类型则调用自己
                if (list.get(i) instanceof List) {
                    sb.append(ListToString((List<?>) list.get(i)));
                    sb.append(SEP1);
                } else if (list.get(i) instanceof Map) {
                    sb.append(MapToString((Map<?, ?>) list.get(i)));
                    sb.append(SEP1);
                } else {
                    sb.append(list.get(i));
                    sb.append(SEP1);
                }
            }
        }
        return sb.toString();
    }

    /**
     * Map转换String
     *
     * @param map            需要转换的Map
     * @return String        转换后的字符串
     */
    public static String MapToString(Map<?, ?> map) {
        StringBuffer sb = new StringBuffer();
        // 遍历map
        for (Object obj : map.keySet()) {
            if (obj == null) {
                continue;
            }
            Object key = obj;
            Object value = map.get(key);
            if (value instanceof List<?>) {
                sb.append(key.toString() + SEP1 + ListToString((List<?>) value));
                sb.append(SEP2);
            } else if (value instanceof Map<?, ?>) {
                sb.append(key.toString() + SEP1 + MapToString((Map<?, ?>) value));
                sb.append(SEP2);
            } else {
                if (value == null) {
                    sb.append(key.toString() + SEP3 + "0");
                    sb.append(SEP2);
                } else {
                    sb.append(key.toString() + SEP3 + value.toString());
                    sb.append(SEP2);
                }
            }
        }
        return sb.toString();
    }

    /**
     * String转换Map
     *
     * @param mapText            需要转换的字符串
     * @return Map<?,?>
     */
    public static Map<String, Object> StringToMap(String mapText) {

        if (mapText == null || mapText.equals("")) {
            return null;
        }
        mapText = mapText.substring(1);

        Map<String, Object> map = new HashMap<String, Object>();
        String[] text = mapText.split("\\" + SEP2); // 转换为数组
        for (String str : text) {
            String[] keyText = str.split(SEP3); // 转换key与value的数组
            if (keyText.length < 1) {
                continue;
            }
            String key = keyText[0]; // key
            String value = keyText[1]; // value
            if (value.charAt(0) == 'M') {
                Map<?, ?> map1 = StringToMap(value);
                map.put(key, map1);
            } else if (value.charAt(0) == 'L') {
                List<?> list = StringToList(value);
                map.put(key, list);
            } else {
                map.put(key, value);
            }
        }
        return map;
    }

    /**
     * String转换List
     *
     * @param listText            需要转换的文本
     * @return List<?>
     */
    public static List<Object> StringToList(String listText) {
        if (listText == null || listText.equals("")) {
            return null;
        }
        listText = listText.substring(0);

        List<Object> list = new ArrayList<Object>();
        String[] text = listText.split("\\" + SEP1);
        String listStr = "";
        boolean flag = false;
        for (String str : text) {
            if (!str.equals("")) {
                if (str.charAt(0) == 'M') {
                    Map<?, ?> map = StringToMap(str);
                    list.add(map);
                } else if (str.charAt(0) == 'L' || flag) {
                    flag = true;
                    listStr += str + SEP1;
                } else {
                    list.add(str);
                }
            }
            if (str.equals("")) {
                flag = false;
                List<?> lists = StringToList(listStr);
                list.add(lists);
            }
        }
        return list;
    }

    public static void main(String[] args) {
        // 1. List转换String
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        String listToString = ListToString(list);
        System.out.println("List转换String:" + listToString);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "刘德华");
        map.put("age", 56);
        map.put("address", "北京市海淀区");
        // 2. Map转换String
        String mapToString = MapToString(map);
        System.out.println("Map转换String: " + mapToString);
        // 3. String转换Map
        Map<String, Object> map1 = StringToMap(mapToString);
        System.out.println("String转换Map: " + map1);
        // 4. String转换List
        List<Object> list1 = StringToList(listToString);
        System.out.println("String转换List: " + list1);
    }
}

(2)控制台输出如下:

 二、数据获取

(1)数据获取的具体代码实例:

 public static void main(String[] args) {
        // 1.数据准备
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("name", "尼古拉斯赵六");
        map.put("age", 25);
        map.put("address", "广东广州");
        Map<String,Object> map1 = new HashMap<>();
        map1.put("name", "令狐冲");
        map1.put("age", 26);
        map1.put("address", "陕西西安");
        Map<String,Object> map2 = new HashMap<>();
        map2.put("name", "李思思");
        map2.put("age", 24);
        map2.put("address", "中国上海");
        list.add(map);
        list.add(map1);
        list.add(map2);
        System.out.println("原始数据:"+list);

        // 2.根据name转成Map
        Map<Object, Map<String, Object>> resultMap =
                list.stream().collect(Collectors.toMap(m -> m.get("name"), m -> m));
        System.out.println("根据name转成Map的结果:"+resultMap);
        // 3.根据name转成List
        List<Object> names = list.stream().map(m -> m.get("name")).collect(Collectors.toList());
        System.out.println("根据name转成List的结果;"+names);

        List<User> jsonArray = (List<User>)JSON.parseArray(JSON.toJSONString(list), User.class);
        System.out.println(jsonArray);

        // 4.将List<Map<String, Object>>转换为List<Object>
        List<Object> listObject = list.stream()
                .flatMap(m -> m.values().stream())
                .collect(Collectors.toList());
        System.out.println(listObject);
    }

(2)控制台输出如下:

 三、Map数据操作

Map是我们日常编程中十分常用的数据接口,的在JDK8中,Map引入了几个新方法,可以简化我们对Map中数据的操作。

getOrDefault

这个方法名很直观,见名知意:尝试获取key对应的值,如果未获取到,就返回默认值。

看一个使用的例子,新写法会比老写法更加简洁:

private static void testGetOrDefault() {
    Map<String, String> map = new HashMap<>(4);
    map.put("123", "123");
    String key = "key";
    String defaultValue = "defaultValue";

    // 老写法
    String oldValue = defaultValue;
    if (map.containsKey(key)) {
        oldValue = map.get(key);
    }
    System.out.println("oldValue = " + oldValue);

    // 新写法
    String newValue = map.getOrDefault(key, defaultValue);
    System.out.println("newValue = " + newValue);
}

foreach

看方法名也可以知道,这个方法是遍历map的数据使用的。

如果没有foreach,我们遍历map的时候一般是使用增强for循环,有了这个方法后,可以更加方便使用entry中的key和val:

private static void testForeach() {
    Map<String, String> map = new HashMap<>(4);
    map.put("123", "123");

    // 老写法
    for (Map.Entry<String, String> entry : map.entrySet()) {
        System.out.printf("老写法 key = %s, value = %s%n", entry.getKey(), entry.getValue());
    }

    // 新写法
    map.forEach((key, value) -> System.out.printf("新写法 key = %s, value = %s%n", key, value));
}

merge

从名字可以想到,是合并entry使用的,但是具体是怎么合并呢?

看一下日常最常用的Map实现类HashMap对merge方法的实现

@Override
public V merge(K key, V value,
               BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    if (value == null || remappingFunction == null)
        throw new NullPointerException();
    int hash = hash(key);
    Node<K,V>[] tab; Node<K,V> first; int n, i;
    int binCount = 0;
    TreeNode<K,V> t = null;
    Node<K,V> old = null;
    if (size > threshold || (tab = table) == null ||
        (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((first = tab[i = (n - 1) & hash]) != null) {
        if (first instanceof TreeNode)
            old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);
        else {
            Node<K,V> e = first; K k;
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k)))) {
                    old = e;
                    break;
                }
                ++binCount;
            } while ((e = e.next) != null);
        }
    }
    if (old != null) {
        V v;
        if (old.value != null) {
            int mc = modCount;
            v = remappingFunction.apply(old.value, value);
            if (mc != modCount) {
                throw new ConcurrentModificationException();
            }
        } else {
            v = value;
        }
        if (v != null) {
            old.value = v;
            afterNodeAccess(old);
        }
        else
            removeNode(hash, key, null, false, true);
        return v;
    } else {
        if (t != null)
            t.putTreeVal(this, tab, hash, key, value);
        else {
            tab[i] = newNode(hash, key, value, first);
            if (binCount >= TREEIFY_THRESHOLD - 1)
                treeifyBin(tab, hash);
        }
        ++modCount;
        ++size;
        afterNodeInsertion(true);
        return value;
    }
}

代码比较长,但是实现的效果比较容易描述:这个方法接收3个参数:key、value、function。

  • 如果key存在,将value按照function做1次计算后,更新到Map中
  • 如果key不存在,将key-value放入Map中

这个方法在某些场景中挺好用的,代码简洁易懂,例如:我们有1个List,要统计List中每个元素出现的次数。我们要实现的逻辑是,遍历List中的每个元素,如果这个元素在Map中存在,Map中的值+1;如果不存在,则放入Map中,次数(值)为1。

private static void testMerge() {
    Map<String, Integer> cntMap = new HashMap<>(8);
    List<String> list = Arrays.asList("apple", "orange", "banana", "orange");

    // 老写法
    for (String item : list) {
        if (cntMap.containsKey(item)) {
            cntMap.put(item, cntMap.get(item) + 1);
        } else {
            cntMap.put(item, 1);
        }
    }

    // 新写法
    for (String item : list) {
        cntMap.merge(item, 1, Integer::sum);
    }
}

可以看到我们使用merge方法的话,只用1行就简洁实现了这个逻辑。

putIfAbsent

也是一个见名知意的方法:不存在key或者值为null时,才将键值对放入Map。跟put方法相比,这个方法不会直接覆盖已有的值,在不允许覆盖旧值的场景使用起来会比较简洁。

private static void testPutIfAbsent() {
    Map<String, Integer> scoreMap = new HashMap<>(4);
    scoreMap.put("Jim", 88);
    scoreMap.put("Lily", 90);

    // 老写法
    if (!scoreMap.containsKey("Lily")) {
        scoreMap.put("Lily", 98);
    }

    // 新写法
    scoreMap.putIfAbsent("Lily", 98);
}

computer

computer方法需要传入2个参数:key、function。主要有3步操作

  • 获取到key对应的oldValue,可能为null
  • 经过function计算获取newValue
  • put(key, newValue)

还是以刚刚统计单次次数需求为例,看一下computer的写法:

private static void testComputer() {
    Map<String, Integer> cntMap = new HashMap<>(8);
    List<String> list = Arrays.asList("apple", "orange", "banana", "orange");

    // 老写法
    for (String item : list) {
        if (cntMap.containsKey(item)) {
            cntMap.put(item, cntMap.get(item) + 1);
        } else {
            cntMap.put(item, 1);
        }
    }

    // 新写法
    for (String item : list) {
        cntMap.compute(item, (k, v) -> {
            if (v == null) {
                v = 1;
            } else {
                v += 1;
            }
            return v;
        });
    }
}

computeIfAbsent

看名字就知道是compute方法衍生出来的方法,这个方法只在key不存在的时候,执行computer计算,如果说key对应的value存在,就直接返回这个value。

例如,我们需要计算斐波那锲数列的时候,可以使用这个方法来简化代码:

private static void testComputerIfAbsent() {
    Map<Integer, Integer> fabMap = new ConcurrentHashMap<>(16);
    fabMap.put(0, 1);
    fabMap.put(1, 1);
    System.out.println(fab(5, fabMap));
}

private static Integer fab(Integer index, Map<Integer, Integer> fabMap) {
    return fabMap.computeIfAbsent(index, i -> fab(i - 2, fabMap) + fab(i - 1, fabMap));
}

computeIfPresent

这个是computeIfAbsent的姊妹方法,区别在于,这个方法是只有key存在的时候,才去执行computer计算和值的更新。

replace

这个方法的效果是:

  • 如果key存在,则更新值
  • 如果key不存在,什么也不做

 

posted @ 2024-10-28 11:51  [奋斗]  阅读(50)  评论(0编辑  收藏  举报