深度复制2D MutableList的简洁方法是什么? [英] What is concise way of deep-copying a 2D MutableList?

查看:69
本文介绍了深度复制2D MutableList的简洁方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该元素已经实现了深度复制.

  fun< T:DeepCopiable>f(a:MutableList< MutableList< T>)> {val复制= a.map {it.map {it.deepCopy()} .toMutableList()} .toMutableList()...} 

我正在使用这种代码,但是看起来很冗长.

解决方案

由于类型系统中的限制,在不绕过类型安全性的情况下,不能将这个问题推广到单个函数中(并且由于JVM类型擦除,您肯定不会这样做)想要在涉及泛型的情况下进入 兔子洞¹).

但是,您可以编写扩展程序功能的 链,以实现深度复制模式,并在类型安全的情况下每增加一个维度就将其委托给前一个功能:

 私有类型别名I< E>=可迭代的< E>私有类型别名Copy< E>=(E)->E私人内联乐趣< T,R>I T.mapToMutable(transform:(T)-R):I R= mapTo(mutableListOf(),transform)有趣的< E>I.deepCopy1(c:Copy< E>)= mapToMutable {c(it)}有趣的< E>I< E> .deepCopy2(c:复制< E>)= mapToMutable {it.deepCopy1(c)}有趣的< E>I< I> .deepCopy3(c:Copy< E>)= mapToMutable {it.deepCopy2(c)}有趣的< E>I< I< E>> .deepCopy4(c:Copy< E>)= mapToMutable {it.deepCopy3(c)}有趣的< E>I< I< I< E>> .deepCopy5(c:Copy E>)= mapToMutable {it.deepCopy4(c)} 

由于JVM类型擦除,函数需要使用不同的名称( @JVMName 由于类型干扰的含糊性²而无济于事).类型别名用于防止水平空间爆炸³,并且通过通用的复制功能参数将功能集与可深度复制的接口分离.

示例用法:

  fun main(args:Array< String>){数据类IntHolder(变量值:Int)val original = List(3){a->清单(3){b->IntHolder(a + b)}}val复制= original.deepCopy2 {it.copy()}原始的[0] [0] .value = 18258125println("original = $ original")println("copied = $ copied")} 

->

 原始= [[IntHolder(值= 18258125),IntHolder(值= 1),IntHolder(值= 2)],[IntHolder(值= 1),IntHolder(值= 2),IntHolder(值= 3)],[IntHolder(值= 2),IntHolder(值= 3),IntHolder(值= 4)]]复制= [[IntHolder(value = 0),IntHolder(value = 1),IntHolder(value = 2)],[IntHolder(value = 1),IntHolder(value = 2),IntHolder(value = 3)],[IntHolder(值= 2),IntHolder(值= 3),IntHolder(值= 4)]] 


[1]:由于泛型类型转换由编译器在运行时执行,因此从 List< Foo> List< Baz> 的转换将始终在运行时成功,但稍后在访问强制转换列表时失败.实现提到的魔术单一功能"是可能的,但是稍有错误就会导致返回的数据结构在访问类强制转换异常时似乎随机"失败.

[2]: Iterable< Iterable< Foo>> 类型的值同时满足这两个条件

乐趣< T>Iterable< T> .baz()(T = Iterable< Foo> )和
fun< T>Iterable< Iterable< T> .baz()(T = Foo )

由于这个原因,如果链中的所有方法都具有相同的函数名称,但具有不同的JVM名称,则编译器将无法确定要使用的正确方法.

[3]:

可重复性可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代<可迭代>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

The element already implemented deep copying.

fun <T : DeepCopiable> f(a: MutableList<MutableList<T>>) {
    val copied = a.map { it.map { it.deepCopy() }.toMutableList() }.toMutableList()
    ...
}

I am using this kind of code, but it seems verbose.

解决方案

Due to restrictions in the type system, this problem cannot be generalized to a single functon without bypassing type safety (and due to JVM type erasure you definitely don't want to go that rabbit hole when generics are involved¹).

However, you can write a chain of extension functions implementing a deep-copy pattern, delegating to the previous function for every increase in dimension, in a type safe matter:

private typealias I<E> = Iterable<E>
private typealias Copy<E> = (E) -> E
private inline fun <T, R> I<T>.mapToMutable(transform: (T) -> R): I<R> = mapTo(mutableListOf(), transform)
fun <E> I<E>.deepCopy1(c: Copy<E>) = mapToMutable { c(it) }
fun <E> I<I<E>>.deepCopy2(c: Copy<E>) = mapToMutable { it.deepCopy1(c) }
fun <E> I<I<I<E>>>.deepCopy3(c: Copy<E>) = mapToMutable { it.deepCopy2(c) }
fun <E> I<I<I<I<E>>>>.deepCopy4(c: Copy<E>) = mapToMutable { it.deepCopy3(c) }
fun <E> I<I<I<I<I<E>>>>>.deepCopy5(c: Copy<E>) = mapToMutable { it.deepCopy4(c) }

Due to JVM type erasure, the functions need different names (@JVMName does not help due to type interference ambiguity²). Type aliases are used to prevent horizontal space explosion³, and the function set is uncoupled from the deep-copiable interface via a generic copy function parameter.

Example usage:

fun main(args: Array<String>) {
    data class IntHolder(var value: Int)
    val original = List(3) { a ->
        List(3) { b ->
            IntHolder(a + b)
        }
    }

    val copied = original.deepCopy2 { it.copy() }
    original[0][0].value = 18258125
    println("original=$original")
    println("copied  =$copied")
}

->

original=[[IntHolder(value=18258125), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]
copied  =[[IntHolder(value=0), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]


[1]: Because generic type casts are performed by the compiler at runtime, a cast from List<Foo> to List<Baz> will always succeed at runtime, but fail later upon access of the casted list. Implementing mentioned magic "single function" is possible, but the slightest of error would result in a returned data structure that fails seemingly "random" upon access with class cast exceptions.

[2]: A value of type Iterable<Iterable<Foo>> satisfies both

fun <T> Iterable<T>.baz() (T = Iterable<Foo>) and
fun <T> Iterable<Iterable<T>.baz() (T = Foo)

Due to this, the compiler would not be able to determine the right method to use if all methods in the chain have the same function name, but different JVM names.

[3]:

Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<ithinkyougetthepoint>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

这篇关于深度复制2D MutableList的简洁方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆