下面列出了com.google.common.collect.MapDifference#entriesDiffering ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() {
Map<String, String> asia1 = new HashMap<String, String>();
asia1.put("Japan", "Tokyo");
asia1.put("South Korea", "Seoul");
asia1.put("India", "New Delhi");
Map<String, String> asia2 = new HashMap<String, String>();
asia2.put("Japan", "Tokyo");
asia2.put("China", "Beijing");
asia2.put("India", "Delhi");
MapDifference<String, String> diff = Maps.difference(asia1, asia2);
Map<String, ValueDifference<String>> entriesDiffering = diff.entriesDiffering();
assertFalse(diff.areEqual());
assertEquals(1, entriesDiffering.size());
assertThat(entriesDiffering, hasKey("India"));
assertEquals("New Delhi", entriesDiffering.get("India").leftValue());
assertEquals("Delhi", entriesDiffering.get("India").rightValue());
}
protected static <T extends Identifiable> Changes<T> changes(Iterable<T> newResources, Iterable<T> currentResources) {
Map<Id, T> newIdsToResource = mapById(newResources);
Map<Id, T> currentIdsToResource = mapById(currentResources);
MapDifference<Id, T> diff = difference(newIdsToResource, currentIdsToResource);
Map<Id, MapDifference.ValueDifference<T>> diffs = diff.entriesDiffering();
return new Changes.Builder<T>()
.added(diff.entriesOnlyOnLeft().values())
.removed(diff.entriesOnlyOnRight().values())
.updated(filterKeys(newIdsToResource, diffs::containsKey).values())
.build();
}
public Map<String, ValueDifference<String>> getPreferenceChanges() {
Map<String, String> currentSettings = Maps.newHashMapWithExpectedSize(keys.length);
for (String key : keys) {
currentSettings.put(key, preferenceStore.getString(key));
}
MapDifference<String, String> mapDifference = Maps.difference(currentSettings, originalSettings);
Map<String, ValueDifference<String>> entriesDiffering = mapDifference.entriesDiffering();
return entriesDiffering;
}
/**
* @return the difference between oldProps and newProps.
*/
public static String getPropertyDiff(Props oldProps, Props newProps) {
final StringBuilder builder = new StringBuilder("");
// oldProps can not be null during the below comparison process.
if (oldProps == null) {
oldProps = new Props();
}
if (newProps == null) {
newProps = new Props();
}
final MapDifference<String, String> md =
Maps.difference(toStringMap(oldProps, false), toStringMap(newProps, false));
final Map<String, String> newlyCreatedProperty = md.entriesOnlyOnRight();
if (newlyCreatedProperty != null && newlyCreatedProperty.size() > 0) {
builder.append("Newly created Properties: ");
newlyCreatedProperty.forEach((k, v) -> {
builder.append("[ " + k + ", " + v + "], ");
});
builder.append("\n");
}
final Map<String, String> deletedProperty = md.entriesOnlyOnLeft();
if (deletedProperty != null && deletedProperty.size() > 0) {
builder.append("Deleted Properties: ");
deletedProperty.forEach((k, v) -> {
builder.append("[ " + k + ", " + v + "], ");
});
builder.append("\n");
}
final Map<String, MapDifference.ValueDifference<String>> diffProperties = md.entriesDiffering();
if (diffProperties != null && diffProperties.size() > 0) {
builder.append("Modified Properties: ");
diffProperties.forEach((k, v) -> {
builder.append("[ " + k + ", " + v.leftValue() + "-->" + v.rightValue() + "], ");
});
}
return builder.toString();
}
@Test
public void testWriteFormatUnchanged() {
// Attempts to flag any changes in the storage format. While thorough, this check is not
// complete. It attempts to capture the entire schema by synthesizing a fully-populated
// instance of each Op type. For TUnions, the struct generator picks an arbitrary field to set,
// meaning that it will only see one of the multiple possible schemas for any given TUnion.
// These generated structs effectively give a view of the struct schema, which is compared to
// golden files in `goldens/current`.
Map<String, String> schemasByName = generateOpSchemas();
File goldensDir = getGoldensDir("current");
Map<String, String> goldensByName = loadGoldenSchemas(goldensDir);
MapDifference<String, String> difference = Maps.difference(goldensByName, schemasByName);
if (difference.areEqual()) {
return;
}
StringBuilder error = new StringBuilder();
StringBuilder remedy = new StringBuilder();
Set<String> removedOps = difference.entriesOnlyOnLeft().keySet();
if (!removedOps.isEmpty()) {
error.append("Removal of storage Op(s): ").append(removedOps)
.append("\nOps may only be removed after a release that")
.append("\n * formally deprecates the Op in release notes")
.append("\n * performs a no-op read of the Op type")
.append("\n * included warning logging when the Op was read")
.append("\n * ensures the Op is removed from storage")
.append("\n\nHowever, you should also consider leaving the Op indefinitely and removing")
.append("\nall fields as a safer alternative.");
remedy.append("deleting the files ")
.append(removedOps.stream()
.map(removed -> new File(goldensDir, removed).getAbsolutePath())
.collect(Collectors.joining(", ")));
}
String goldenChangeInstructions = Streams.concat(
difference.entriesOnlyOnRight().entrySet().stream(),
difference.entriesDiffering().entrySet().stream()
.map(entry ->
new SimpleImmutableEntry<>(entry.getKey(), entry.getValue().rightValue())))
.map(entry -> new StringBuilder()
.append("\n").append(new File(goldensDir, entry.getKey()).getPath()).append(":")
.append("\n").append(entry.getValue())
.toString())
.collect(Collectors.joining("\n"));
Set<String> addedOps = difference.entriesOnlyOnRight().keySet();
if (!addedOps.isEmpty()) {
error.append("Addition of storage Op(s): ").append(addedOps)
.append("\nOps may only be introduced")
.append("\n a.) in a release that supports reading but not writing the Op")
.append("\n b.) in a release that writes the Op only with an operator-controlled flag");
remedy.append("creating the following files")
.append(goldenChangeInstructions);
}
Map<String, ValueDifference<String>> modified = difference.entriesDiffering();
if (!modified.isEmpty()) {
error.append("Schema changes to Op(s): " + modified.keySet())
.append("\nThis check detects that changes occurred, not how the schema changed.")
.append("\nSome guidelines for evolving schemas:")
.append("\n * Introducing fields: you must handle reading records that do not")
.append("\n yet have the field set. This can be done with a backfill routine during")
.append("\n storage recovery if a field is required in some parts of the code")
.append("\n * Removing fields: must only be done after a release in which the field")
.append("\n is unused and announced as deprecated")
.append("\n * Changed fields: the type or thrift field ID of a field must never change");
remedy.append("changing the following files")
.append(goldenChangeInstructions);
}
fail(new StringBuilder()
.append("**** Storage compatibility change detected ****")
.append("\n")
.append(error)
.append("\n\nIf the necessary compatibility procedures have been performed,")
.append("\nyou may clear this check by ")
.append(remedy)
.toString());
}
/**
* @param originalSettings
* the settings before applying the values of the form page
* @param currentSettings
* the settings after collecting the values of the form page
* @return a map keyed by the preference store key (e.g. outlet.es5.autobuilding for compiler (resp. output
* configuration) with name 'es5' and property 'autobuilding') containing old and new value. Only keys whose
* values has been changed are included.
*/
private Map<String, ValueDifference<String>> getPreferenceChanges(Map<String, String> originalSettings,
Map<String, String> currentSettings) {
MapDifference<String, String> mapDifference = Maps.difference(currentSettings, originalSettings);
Map<String, ValueDifference<String>> entriesDiffering = mapDifference.entriesDiffering();
return entriesDiffering;
}
@Test
public void entries_differing() {
MapDifference<Integer, Student> mapDifference = Maps.difference(
geometryClass, gymClass);
System.out.println(mapDifference.entriesDiffering()); // with same keys
Map<Integer, ValueDifference<Student>> sameKeyDifferentValue = mapDifference
.entriesDiffering();
assertThat(sameKeyDifferentValue.keySet(), hasItems(new Integer(789)));
}
/**
* @param originalSettings
* the settings before applying the values of the form page
* @param currentSettings
* the settings after collecting the values of the form page
* @return a map keyed by the preference store key (e.g. outlet.es5.autobuilding for compiler (resp. output
* configuration) with name 'es5' and property 'autobuilding') containing old and new value. Only keys whose
* values has been changed are included.
*/
private Map<String, ValueDifference<String>> getPreferenceChanges(Map<String, String> originalSettings,
Map<String, String> currentSettings) {
MapDifference<String, String> mapDifference = Maps.difference(currentSettings, originalSettings);
return mapDifference.entriesDiffering();
}