Java之常见数据结构合并

本文详细介绍了在Java开发中常见的数据结构和算法合并操作,包括字符串数组去重合并、基础类型数组合并、有序集合整合、二叉树合并、链表合并以及Map合并。此外,还展示了如何将有序数组和链表转化为二叉搜索树。这些方法利用了Java 8的Stream API以及递归等技巧,确保合并过程的效率和有序性。
摘要由CSDN通过智能技术生成

一、通常开发中经常使用到一些API进行相应的业务数据结构合并,已经面试中的一些常用的场景做合并,这里简单整理归纳下吧~

1、字符串数组元素拆开去重后合并.

实现效果如:Stream.of()、Arrays.stream();

String[] string={"array","merge","thread","merge"};

结果:

[array, merge, thread]

    /**
     * 去重合并字符串数组
     *
     * @param source source
     * @return List<String>
     */
    private static List<String> mergeStringArray(String[] source){
        return Stream.of(source).map(num->num.split(",")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
    }

2、合并两个基础类型数组,使用IntStream.concat()方法.

int[] source={1,2,3,5,7};
int[] target={723,44,2,2}; 

方法一:通过Stream的流式合并.

    /**
     * 去重合并两个基础数组
     * @param source 源数组
     * @param target 目标数组
     * @return int[]
     */
    private static int[] mergeArray(int[] source,int[] target){
        if(source.length==0&&target.length==0){
            return new int[0];
        }
        if(source.length==0){
            return target;
        }
        if(target.length==0){
            return source;
        }
        return IntStream.concat(Arrays.stream(source).sorted(), Arrays.stream(target).sorted()).distinct().toArray();
    }

方法二、通过双指针从后遍历来实现.

    /**
     *
     * @param nums1 nums1
     * @param m 长度
     * @param nums2 nums2
     * @param n 长度
     */
    /**
     *循环终止后有三种情况
     * 两个数组都被遍历完,无剩余元素(两数组有效长度相等)**
     * 数组1被遍历完,数组2元素剩余(数组2的有效长度更大)
     * 数组2被遍历完,数组1元素剩余(数组1的有效长度更大)
     * 情况1表示合并完毕
     * 情况2,此时数组2中剩余的元素小于等于已经被合并的元素,将这些元素放在已合并元素之前即可
     * 情况3,数组1中剩余的元素本来就在已经被合并的元素之前,不需要调整
     * 合并完成.
     */
    public static void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1, j = n - 1;
        // 新数组的长度,从后面开始遍历
        // 时间复杂度O(m+n)
        // 空间复杂度O(1)
        int index = m + n - 1;
        while (i >= 0 || j >= 0) {
            // 对应长度相等时候
            if (i >= 0 && j >= 0) {
                nums1[index--] = nums1[i] >= nums2[j] ? nums1[i--] : nums2[j--];
            // 对应数组1元素剩余,排在前面即可
            } else if (i >= 0) {
                nums1[index--] = nums1[i--];
            // 对应数组2元素剩余,排在前面即可
            } else {
                nums1[index--] = nums2[j--];
            }
        }
    }

3、合并两个有序集合.

flatMap(Collection::stream):扁平化处理元素,Stream[]
    /**
     * 合并两个有序集合
     *
     * @param source 源集合
     * @param target 目标集合
     * @return
     */
    public static List<Integer> mergeList(List<Integer> source,List<Integer> target){
        if(CollectionUtils.isEmpty(source)&&CollectionUtils.isEmpty(target)){
            return Collections.EMPTY_LIST;
        }
        if(CollectionUtils.isEmpty(source)){
            return target;
        }
        if(CollectionUtils.isEmpty(target)){
            return source;
        }
        return Stream.of(source,target).flatMap(Collection::stream).distinct().sorted().collect(Collectors.toList());
    }

4、合并两个二叉树,通过树的前序遍历实现,递归解决,但是占用内存.

    /**
     * 合并两个二叉树
     * @param source 源数
     * @param target 目标树
     * @return Node
     */
    public static Node merge(Node source,Node target){
        if(Objects.isNull(source)&&Objects.isNull(target)){
            return null;
        }
        if(Objects.isNull(source)){
            return target;
        }
        if(Objects.isNull(target)){
            return source;
        }
        // 新增节点
        Node node=new Node(source.value+target.value);
        node.left= merge(source.left, target.left);
        node.right=merge(source.right, target.right);
        return node;
    }

5、合并链表,递归实现.

    /**
     * 合并两个有序链表
     * @param list1 链表一
     * @param list2 链表二
     * @return ListNode
     */
    public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null) {
            return list2;
        }
        if (list2 == null) {
            return list1;
        }
        // 递归合并有序链表
        if (list1.value <= list2.value) {
            list1.next = mergeTwoLists(list1.next, list2);
            return list1;
        } else {
            list2.next = mergeTwoLists(list1, list2.next);
            return list2;
        }
    }

6、合并两个Map,使用JAVA8的merge方法. 

    /**
     * 合并两个Map,适用长度不等时候
     *
     * @param map1
     * @param map2
     * @return
     */
    public static Map<String,Integer> mergeMap(Map<String,Integer> map1, Map<String,Integer> map2){
        if(MapUtils.isEmpty(map1)&&MapUtils.isEmpty(map2)){
            return Collections.emptyMap();
        }
        if(MapUtils.isEmpty(map1)){
            return map2;
        }
        if(MapUtils.isEmpty(map2)){
            return map1;
        }
        // 按照两个Map的长度实现
        if(map1.size()>map2.size()){
            map1.forEach((k,v)->{
                map2.merge(k, v, (oldValue,newValue)->(oldValue+newValue));
            });
            return map1;
        }
        map2.forEach((k,v)->{
            map1.merge(k, v, (oldValue,newValue)->(oldValue+newValue));
        });
        return map2;
    }

7、有序数组转换二叉搜索树,递归+二分搜索

    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }
    public TreeNode helper(int[] nums, int left, int right) {
        if (left > right) {
            return null;
        }
        // 总是选择中间位置左边的数字作为根节点,二叉搜索树特点:根节点大于左节点,小于右节点,那么类似二叉搜索树的中序遍历
        int mid = left+(right-left)/2;
        TreeNode root = new TreeNode(nums[mid]);
        // 递归实现
        root.left = helper(nums, left, mid - 1);
        root.right = helper(nums, mid + 1, right);
        return root;
    }

8、有序链表转换值二叉树,递归+快慢指针

// 类似有序数组构造二叉搜索树
    public TreeNode buildTree(ListNode left, ListNode right) {
        if (left == right) {
            return null;
        }
        ListNode mid = getMedian(left, right);
        // 中间节点当做根节点
        TreeNode root = new TreeNode(mid.val);
        root.left = buildTree(left, mid);
        root.right = buildTree(mid.next, right);
        return root;
    }

    // 快慢指针求链表中间节点
    public ListNode getMedian(ListNode left, ListNode right) {
        ListNode fast = left;
        ListNode slow = left;
        while (fast != right && fast.next != right) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

 数组,没排序则先保持有序,然后二分;链表,快慢指针寻找终点,二叉搜索树的中序左根右是有序的,同时注意边界条件,套路了,没啥子难度,熟悉Stream的流式操作。

Dubbo框架的数据结构合并

Merger

package com.alibaba.dubbo.rpc.cluster;

import com.alibaba.dubbo.common.extension.SPI;

@SPI
public interface Merger<T> {

    T merge(T... items);

}

  ShortArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class ShortArrayMerger implements Merger<short[]> {

    @Override
    public short[] merge(short[]... items) {
        int total = 0;
        for (short[] array : items) {
            total += array.length;
        }
        short[] result = new short[total];
        int index = 0;
        for (short[] array : items) {
            for (short item : array) {
                result[index++] = item;
            }
        }
        return result;
    }
}

 SetMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

import java.util.HashSet;
import java.util.Set;

public class SetMerger implements Merger<Set<?>> {

    @Override
    public Set<Object> merge(Set<?>... items) {

        Set<Object> result = new HashSet<Object>();

        for (Set<?> item : items) {
            if (item != null) {
                result.addAll(item);
            }
        }

        return result;
    }
}

 ListMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

import java.util.ArrayList;
import java.util.List;

public class ListMerger implements Merger<List<?>> {

    @Override
    public List<Object> merge(List<?>... items) {
        List<Object> result = new ArrayList<Object>();
        for (List<?> item : items) {
            if (item != null) {
                result.addAll(item);
            }
        }
        return result;
    }

}

  MapMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

import java.util.HashMap;
import java.util.Map;

public class MapMerger implements Merger<Map<?, ?>> {

    @Override
    public Map<?, ?> merge(Map<?, ?>... items) {
        if (items.length == 0) {
            return null;
        }
        Map<Object, Object> result = new HashMap<Object, Object>();
        for (Map<?, ?> item : items) {
            if (item != null) {
                result.putAll(item);
            }
        }
        return result;
    }

}

BooleanArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class BooleanArrayMerger implements Merger<boolean[]> {

    @Override
    public boolean[] merge(boolean[]... items) {
        int totalLen = 0;
        for (boolean[] array : items) {
            totalLen += array.length;
        }
        boolean[] result = new boolean[totalLen];
        int index = 0;
        for (boolean[] array : items) {
            for (boolean item : array) {
                result[index++] = item;
            }
        }
        return result;
    }

}

ByteArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class ByteArrayMerger implements Merger<byte[]> {

    @Override
    public byte[] merge(byte[]... items) {
        int total = 0;
        for (byte[] array : items) {
            total += array.length;
        }
        byte[] result = new byte[total];
        int index = 0;
        for (byte[] array : items) {
            for (byte item : array) {
                result[index++] = item;
            }
        }
        return result;
    }

}

CharArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class CharArrayMerger implements Merger<char[]> {

    @Override
    public char[] merge(char[]... items) {
        int total = 0;
        for (char[] array : items) {
            total += array.length;
        }
        char[] result = new char[total];
        int index = 0;
        for (char[] array : items) {
            for (char item : array) {
                result[index++] = item;
            }
        }
        return result;
    }
}

DoubleArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class DoubleArrayMerger implements Merger<double[]> {

    @Override
    public double[] merge(double[]... items) {
        int total = 0;
        for (double[] array : items) {
            total += array.length;
        }
        double[] result = new double[total];
        int index = 0;
        for (double[] array : items) {
            for (double item : array) {
                result[index++] = item;
            }
        }
        return result;
    }
}
FloatArrayMerger
package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class FloatArrayMerger implements Merger<float[]> {

    @Override
    public float[] merge(float[]... items) {
        int total = 0;
        for (float[] array : items) {
            total += array.length;
        }
        float[] result = new float[total];
        int index = 0;
        for (float[] array : items) {
            for (float item : array) {
                result[index++] = item;
            }
        }
        return result;
    }
}

IntArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class IntArrayMerger implements Merger<int[]> {

    @Override
    public int[] merge(int[]... items) {
        int totalLen = 0;
        for (int[] item : items) {
            totalLen += item.length;
        }
        int[] result = new int[totalLen];
        int index = 0;
        for (int[] item : items) {
            for (int i : item) {
                result[index++] = i;
            }
        }
        return result;
    }

}

LongArrayMerger

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

public class LongArrayMerger implements Merger<long[]> {

    @Override
    public long[] merge(long[]... items) {
        int total = 0;
        for (long[] array : items) {
            total += array.length;
        }
        long[] result = new long[total];
        int index = 0;
        for (long[] array : items) {
            for (long item : array) {
                result[index++] = item;
            }
        }
        return result;
    }
}

ArrayMerger 

package com.alibaba.dubbo.rpc.cluster.merger;

import com.alibaba.dubbo.rpc.cluster.Merger;

import java.lang.reflect.Array;

public class ArrayMerger implements Merger<Object[]> {

    public static final ArrayMerger INSTANCE = new ArrayMerger();

    @Override
    public Object[] merge(Object[]... others) {
        if (others.length == 0) {
            return null;
        }
        int totalLen = 0;
        for (int i = 0; i < others.length; i++) {
            Object item = others[i];
            if (item != null && item.getClass().isArray()) {
                totalLen += Array.getLength(item);
            } else {
                throw new IllegalArgumentException((i + 1) + "th argument is not an array");
            }
        }

        if (totalLen == 0) {
            return null;
        }

        Class<?> type = others[0].getClass().getComponentType();

        Object result = Array.newInstance(type, totalLen);
        int index = 0;
        for (Object array : others) {
            for (int i = 0; i < Array.getLength(array); i++) {
                Array.set(result, index++, Array.get(array, i));
            }
        }
        return (Object[]) result;
    }

}

 MergerFactory

public class MergerFactory {

    /**
     * Merger 对象缓存
     */
    private static final ConcurrentMap<Class<?>, Merger<?>> mergerCache =
            new ConcurrentHashMap<Class<?>, Merger<?>>();

    /**
     * 获得指定类型的Merger对象
     * @param returnType
     * @param <T>
     * @return
     */
    public static <T> Merger<T> getMerger(Class<T> returnType) {
        Merger result;
        // 如果类型是集合
        if (returnType.isArray()) {
            // 获得类型
            Class type = returnType.getComponentType();
            // 从缓存中获得该类型的Merger对象
            result = mergerCache.get(type);
            // 如果为空,则
            if (result == null) {
                // 初始化所有的 Merger 扩展对象,到 mergerCache 缓存中。
                loadMergers();
                // 从集合中取出对应的Merger对象
                result = mergerCache.get(type);
            }
            // 如果结果为空,则直接返回ArrayMerger的单例
            if (result == null && !type.isPrimitive()) {
                result = ArrayMerger.INSTANCE;
            }
        } else {
            // 否则直接从mergerCache中取出
            result = mergerCache.get(returnType);
            // 如果为空
            if (result == null) {
                // 初始化所有的 Merger 扩展对象,到 mergerCache 缓存中。
                loadMergers();
                // 从集合中取出
                result = mergerCache.get(returnType);
            }
        }
        return result;
    }

    /**
     * 初始化所有的 Merger 扩展对象,到 mergerCache 缓存中。
     */
    static void loadMergers() {
        // 获得Merger所有的扩展对象名
        Set<String> names = ExtensionLoader.getExtensionLoader(Merger.class)
                .getSupportedExtensions();
        // 遍历
        for (String name : names) {
            // 加载每一个扩展实现,然后放入缓存。
            Merger m = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(name);
            mergerCache.putIfAbsent(ReflectUtils.getGenericClass(m.getClass()), m);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道之简

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值