假设我有两个像这样的枚举:
from sklearn.decomposition import PCA
import cv2
import numpy as np
image_filepath = 'baby_yoda_image.jpg'
# Loading image from disk.
input_image = cv2.imread(image_filepath)
height = input_image.shape[0]
width = input_image.shape[1]
channels = input_image.shape[2]
# Reshaping image to perform PCA.
print('Input image shape:', input_image.shape)
#--- OUT: (533, 800, 3)
reshaped_image = np.reshape(input_image, (height, width*channels))
print('Reshaped Image:', reshaped_image.shape)
#--- OUT: (533, 2400)
# Applying PCA transformation to image. No whitening is applied to prevent further data loss.
n_components = 64
whitening = False
pca = PCA(n_components, whitening)
compressed_image = pca.fit_transform(reshaped_image)
print('PCA Compressed Image Shape:', compressed_image.shape)
#--- OUT: (533, 64)
print('Compression achieved:', np.around(np.sum(pca.explained_variance_ratio_), 2)*100, '%')
#--- OUT: 97.0 %
# Plotting images.
approximated_image = pca.inverse_transform(compressed_image)
approximated_original_shape_image = np.reshape(approximated_image, (height, width, channels))
cv2.imshow('Input Image', input_image)
cv2.imshow('Compressed Image', approximated_original_shape_image)
cv2.waitKey()
现在,我想实现一个查找表,使用 Map 将这些枚举值与 public enum foo {
FOO1, FOO2, FOO3;
}
public enum bar {
BAR1, BAR2, BAR3;
}
值相关联,并将两个枚举值作为键,这样我就可以使用 Map 实用程序轻松地对映射进行交互,但是除了使用 int
之外,我不知道如何继续,这听起来根本不安全;我正在考虑为两个枚举创建一个超类 fooBar 并使用 Map<Object, int>
,但 AFAIK 枚举不能 Map<fooBar, int>
一个类,或者创建一个带有空体的接口 extend
这两个枚举可以 fooBarInterface
然后使用 implement
。
对于解决此问题的好方法有什么想法吗?将枚举合并为一个对我来说不是一种选择。
答案 0 :(得分:1)
FooBarInterface
) 的想法很好,可以解决问题。Enum
作为映射键类型:Map<Enum<?>, Integer> lookupTable = Map.of(Foo.FOO1, 1, Foo.FOO2, 3, Foo.FOO3, 5, Bar.BAR1, 6, Bar.BAR2, 8, Bar.BAR3, 11);
。在这两种情况下,根据情况,我可能仍会保留两个单独的地图,并且仅在需要时将它们合并以进行迭代。
为了进一步推进这个想法,我什至可能会考虑开发一个关于两个地图条目集联合的视图。您需要开发自己的 Iterator
实现,该实现首先迭代第一个映射的条目集,然后是第二个映射,最后表示迭代结束(hasNext()
返回 false
) .
类型安全?你说你想要的东西有一个固有的“类型不安全”。和它一起生活。除了 java.util.Map
接口的基本类型问题之外,这只是一个很小的成本:它的 get
方法接受任何对象,而不仅仅是声明键类型的对象(这是由于历史原因)。< /p>
PS 在我使用的 Java 版本中,int
根本不能是 Map
的值类型或泛型类型的类型参数。它可能是后来添加的。如果没有,您将不得不使用 Integer
。
迭代两个(或更多)映射的一种方法是通过流操作:
Map<Foo, Integer> fooLookupTable = new EnumMap<>(Map.of(Foo.FOO1, 2, Foo.FOO2, 3, Foo.FOO3, 8));
Map<Bar, Integer> barLookupTable = new EnumMap<>(Map.of(Bar.BAR1, 4, Bar.BAR2, 6, Bar.BAR3, 11));
Stream.of(fooLookupTable, barLookupTable)
.flatMap(m -> m.entrySet().stream())
.forEach(e -> System.out.format("%4s (%3s) %2d%n",
e.getKey(), e.getKey().getClass().getSimpleName(), e.getValue()));
输出:
<块引用>FOO1 (Foo) 2
FOO2 (Foo) 3
FOO3 (Foo) 8
BAR1 (Bar) 4
BAR2 (Bar) 6
BAR3 (Bar) 11
为了保持两个单独的查找映射并同时迭代它们,您可能需要如下代码:
Map<Foo, Integer> fooLookupTable = new EnumMap<>(Map.of(Foo.FOO1, 2, Foo.FOO2, 3, Foo.FOO3, 8));
Map<Bar, Integer> barLookupTable = new EnumMap<>(Map.of(Bar.BAR1, 4, Bar.BAR2, 6, Bar.BAR3, 11));
IterableUnion<Entry<? extends Enum<?>, Integer>> union
= new IterableUnion<>(fooLookupTable.entrySet(), barLookupTable.entrySet());
for (Map.Entry<? extends Enum<?>, Integer> e : union) {
System.out.format("%4s (%3s) %2d%n",
e.getKey(), e.getKey().getClass().getSimpleName(), e.getValue());
}
输出为:
<块引用>FOO1 (Foo) 2
FOO2 (Foo) 3
FOO3 (Foo) 8
BAR1 (Bar) 4
BAR2 (Bar) 6
BAR3 (Bar) 11
我正在使用如下所示的 IterableUnion
类。我认为它有一些通用性:您可以迭代两个以上的集合或其他实现 Iterable
的东西,并且元素类型可能会有所不同。
public class IterableUnion<E> implements Iterable<E> {
private class UnionIterator implements Iterator<E> {
private int index = 0;
private Iterator<? extends E> iteratorForIndex;
UnionIterator() {
if (iterables.length > 0) {
iteratorForIndex = iterables[0].iterator();
}
}
@Override
public boolean hasNext() {
if (index == iterables.length) {
return false;
}
while (true) {
if (iteratorForIndex.hasNext()) {
return true;
}
index++;
if (index == iterables.length) {
return false;
}
iteratorForIndex = iterables[index].iterator();
}
}
@Override
public E next() {
if (! hasNext()) {
throw new NoSuchElementException();
}
return iteratorForIndex.next();
}
}
private final Iterable<? extends E>[] iterables;
@SafeVarargs
public IterableUnion(Iterable<? extends E>... iterables) {
this.iterables = iterables;
}
@Override
public Iterator<E> iterator() {
return new UnionIterator();
}
}