我有一個Map<Integer, Character> alphabetMap,其中包含從數字到字母的鏈接。
例如: [1: 'A', 2: 'B', ... , 26: 'Z']
我有一個 rotate() 方法,它應該將條目與更改鏈接
首次使用該方法后,我的地圖應該是 [1: 'Z', 2: 'A', 3: 'B', ... , 26: 'Y']
這是我目前的實作:
public void rotate() {
final Map<Integer, Character> tempMap = new HashMap<>();
alphabetMap.forEach((key, value) -> tempMap.put(key == 26 ? 1 : key 1, value));
alphabetMap = tempMap;
}
有沒有其他方法/演算法可以更快地“旋轉”我的條目?
uj5u.com熱心網友回復:
對于“更快”的旋轉,可以用串列替換地圖,然后Collections.rotate可以為此目的使用方法。然后可以通過 range 中的索引訪問串列元素[0..25]。
或者可以實作一個小的包裝類:
static class MyCharMap {
private List<Character> chars = IntStream
.rangeClosed('A', 'Z')
.mapToObj(c -> (char)c)
.collect(Collectors.toList());
public void rotate() {
Collections.rotate(chars, 1);
}
public Character get(Integer i) {
assert(1 <= i && i <= 26);
return chars.get(i - 1);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(4 * chars.size() 2);
sb.append('{');
for (int i = 0, n = chars.size(); i < n; i ) {
if (i > 0) sb.append(", ");
sb.append(i 1).append(':').append(chars.get(i));
}
sb.append('}');
return sb.toString();
}
}
測驗:
MyCharMap chars = new MyCharMap();
chars.rotate();
chars.rotate();
System.out.println(chars);
System.out.println(chars.get(1));
輸出:
{1:Y, 2:Z, 3:A, 4:B, 5:C, 6:D, 7:E, 8:F, 9:G, 10:H, 11:I, 12:J, 13:K, 14:L, 15:M, 16:N, 17:O, 18:P, 19:Q, 20:R, 21:S, 22:T, 23:U, 24:V, 25:W, 26:X}
Y
uj5u.com熱心網友回復:
如果使用地圖,您的方法沒有任何問題。但是由于旋轉必須相對于某些順序并且地圖是無序的,因此您可能希望使用Alex Rudenko建議的 List 。
這是使用地圖的另一種選擇。對于提供的具有從 1 開始的順序整數鍵的映射,它允許任意數量的左或右旋轉(基于符號)。它還通過使用remainder operator. 對于左或右旋轉偏移,只需計算并更改地圖并回傳以供后續處理。
BiFunction<Map<Integer, Character>, Integer, Map<Integer, Character>> rotate =
(mp, cnt) -> {
int size = mp.values().size();
int count = cnt < 0 ? size (cnt % size) - 1 :
cnt - 1;
return mp.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<>(
(e.getKey() count) % size 1,
e.getValue()))
.collect(Collectors.toMap(e -> e.getKey(),
e -> e.getValue()));
};
System.out.println(map); // original map - 10 elements
map = rotate.apply(map,1); // right one - starting at J
System.out.println(map);
map = rotate.apply(map,-2); // left two, skipping A, going to B
System.out.println(map);
map = rotate.apply(map, -21);// Essentially left one going to C
System.out.println(map);
map = rotate.apply(map, 22); // Essentially right two going to A
System.out.println(map);
印刷
{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J}
{1=J, 2=A, 3=B, 4=C, 5=D, 6=E, 7=F, 8=G, 9=H, 10=I}
{1=B, 2=C, 3=D, 4=E, 5=F, 6=G, 7=H, 8=I, 9=J, 10=A}
{1=C, 2=D, 3=E, 4=F, 5=G, 6=H, 7=I, 8=J, 9=A, 10=B}
{1=A, 2=B, 3=C, 4=D, 5=E, 6=F, 7=G, 8=H, 9=I, 10=J}
lambda 版本可以很容易地替換為采用單個旋轉值并在固定地圖上作業的常規方法。
uj5u.com熱心網友回復:
正如@code-apprentice 在評論中所述
由于鍵是按數字順序排列的,因此我建議使用陣列或串列而不是映射。
如果您仍想回傳地圖,則可以將該Collections.rotate(...)方法與重建預期地圖結合使用。
BiFunction<List<?>, Integer, Map<Integer, ?>> rotate =
(list, distance) -> {
Function<List<?>, Map<Integer, ?>> setMap = (arrayList) -> IntStream.range(0, arrayList.size())
.boxed()
.collect(Collectors.toMap(arrayList::get, Function.identity()))
.entrySet()
.stream()
.peek(e -> e.setValue(e.getValue() 1))
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
Collections.rotate(list, distance);
return setMap.apply(list);
};
System.out.println(rotate.apply(Arrays.asList('A', 'B', 'C', 'D'), 1)); // {1=D, 2=A, 3=B, 4=C}
System.out.println(rotate.apply(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"), -3)); // {1=Tiffany, 2=Mathew, 3=Peter, 4=James, 5=Sam}
uj5u.com熱心網友回復:
根據Alex Rudenko 的回答,您可以創建一個在幕后使用 Collections.rotate(...)的自定義地圖。
自定義地圖:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class MyMap {
private static int counter = 0;
private final Map<Integer, ?> initMap;
private final List<?> list;
private Map<Integer, ?> rotatedMap;
public MyMap(List<?> list) {
this.list = list;
this.initMap = setMap(this.list);
this.rotatedMap = cloneMap(this.initMap);
}
private Map<Integer, ?> setMap(List<?> list) {
return IntStream.range(0, list.size())
.boxed()
.collect(Collectors.toMap(list::get, Function.identity()))
.entrySet()
.stream()
.peek(e -> e.setValue(e.getValue() 1))
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
}
private Map<Integer, ?> cloneMap(Map<Integer, ?> map) {
return map.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
public Map<Integer, ?> get() {
counter = 0;
return rotatedMap;
}
public MyMap reset() {
counter = 0;
this.rotatedMap = cloneMap(this.initMap);
return this;
}
public MyMap rotate() {
return rotateMap( counter);
}
public MyMap rotate(int distance) {
return rotateMap(distance);
}
private List<?> cloneList(List<?> list) {
return list.stream().map(e -> e).collect(Collectors.toList());
}
private MyMap rotateMap(int distance) {
List<?> list = cloneList(this.list);
Collections.rotate(list, distance);
this.rotatedMap = setMap(list);
return this;
}
public String toString() {
return rotatedMap.toString();
}
}
示例 1(旋轉兩次、重置旋轉、旋轉兩次。):
// Rotate twice, Reset rotation, Rotate twice.
MyMap myCharMap1 = new MyMap(Arrays.asList('A', 'B', 'C', 'D'));
System.out.println(myCharMap1
.rotate(2)
.reset()
.rotate().rotate()
.get()); // {1=C, 2=D, 3=A, 4=B}
示例 2(旋轉三次。可以旋轉字串串列):
//Rotate thrice.
MyMap myMap = new MyMap(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"));
System.out.println(myMap.rotate(3).get()); // {1=Sam, 2=Tiffany, 3=Mathew, 4=Peter, 5=James}
示例 3(旋轉一次。也可以旋轉數字串列):
// Rotate once. Can rotate a numeric list as well.
MyMap myDigitMap3 = new MyMap(Arrays.asList(38, 56, 98, 160));
System.out.println(myDigitMap3.rotate(1).get()); // {1=160, 2=38, 3=56, 4=98}
示例 4(可以接受負旋轉):
//Can accept negative rotations.
MyMap myMap = new MyMap(Arrays.asList("Peter", "James", "Sam", "Tiffany", "Mathew"));
System.out.println(myMap.rotate(-3).get()); // {1=Tiffany, 2=Mathew, 3=Peter, 4=James, 5=Sam}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/411542.html
標籤:
上一篇:完全二叉樹時間復雜度
