Reputation: 177
I have a list of maps List<Map<String,String>> input
.
Which can be represented in the following manner:
[{AddressField=AddressUsageType, AddressValue=PRINCIPAL},
{AddressField=StreetNumber, AddressValue=2020},
{AddressField=StreetName, AddressValue=Some street}]
I would like to get the AddressValue
for a particular AddressField
.
For example, I want to get the value "PRINCIPAL"
for the key "AddressUsageType"
.
I have tried using filters and many other MAP functions, but couldn't end up with a proper solution.
This is my code snippet that gets the value of 1st key-value pair:
DataTable table;
List<Map<String,String>> input= table.asMaps(String.class, String.class);
String AddressField = input.get(0).get("AddressField");
String AddressValue = input.get(0).get("AddressValue");
System.out.println("AddressField " +AddressField);
System.out.println("AddressValue " +AddressValue);
Here is the output of the above snippet:
AddressField AddressUsageType
AddressValue PRINCIPAL
Upvotes: 0
Views: 2909
Reputation: 6840
Since in your code you have a List
where each element is a Map
with a single mapping, you could stream the list and filter for the first map containing the value AddressUsageType
.
Your code could be written like this:
Map<String, String> map = myList.stream()
.filter(m -> m.values().contains("AddressUsageType"))
.findFirst()
.orElse(null);
if (map != null) {
System.out.println("AddressField " + map.get("AddressField"));
System.out.println("AddressValue " + map.get("AddressValue"));
}
Here is also a test main at OneCompiler.
Upvotes: 1
Reputation: 28978
I would like to get the value of AddressValue from value of AddressField. For eg.,
I want to get the
value "PRINCIPAL"
from thekey value "AddressUsageType"
You are misusing the Map
here. Because every map is expected to have a limited, well-defined set of keys, each of which has a particular meaning in your domain. And every map is mean to represent a some kind of address.
It's highly advisable to group these data into a custom object as soon as it has a particular meaning in your domain model.
The advantages are:
String
.I understand that it might the code that was developed long ago by someone else, or you might think that for now it's easier to store the data this was. But the more you're postponing the refactoring, the more expensive it becomes.
By treating the object as a collection, you might and up with deeply nested collections like map of maps or map of list of maps that will affect maintainability of code.
That how you can approach this task if you would choose to group the data into a domain class.
For sake of simplicity and conciseness, I would use Java 16 records.
public record UserAddress(AddressUsageType addressUsageType, int streetNumber, String streetName) {}
And AddressUsageType
will be represented as enum
. If I understood correctly there will a limited number of address type, so it's less error-prone to store this data as enum instead of relying on string values, and also gives few extra opportunities.
public enum AddressUsageType { PRINCIPAL, OTHER_TYPE }
And that's how you can extract a particular field from each UserAddress
object in a list, by being able to benefit from its type instead of treating them as string:
public static <T> List<T> getAddressValue(List<UserAddress> addresses,
Function<UserAddress, T> keyExtractor) {
return addresses.stream()
.map(keyExtractor)
.toList(); // available with Java 16 onwards
}
The method shown above expects a list of addresses and a function which extracts a particular property from an addresses object.
main()
- demo
public static void main(String[] args) {
List<UserAddress> addresses =
List.of(new UserAddress(AddressUsageType.PRINCIPAL, 71, "greenStreet"),
new UserAddress(AddressUsageType.PRINCIPAL, 83, "purpleStreet"),
new UserAddress(AddressUsageType.OTHER_TYPE, 85, "pinkStreet"));
List<AddressUsageType> addressUsageTypes = getAddressValue(addresses, UserAddress::addressUsageType);
List<Integer> streetNumbers = getAddressValue(addresses, UserAddress::streetNumber);
List<String> streetNames = getAddressValue(addresses, UserAddress::streetName);
System.out.println("AddressUsageTypes:\n" + addressUsageTypes);
System.out.println("StreetNumbers:\n" + streetNumbers);
System.out.println("StreetNames:\n" + streetNames);
}
Output
AddressUsageTypes:
[PRINCIPAL, PRINCIPAL, OTHER_TYPE]
StreetNumbers:
[71, 83, 85]
StreetNames:
[greenStreet, purpleStreet, pinkStreet]
Upvotes: 1
Reputation: 6435
Filter the input to retain only maps which contain AddressField=AddressUsageType
. Then extract the AddressValue
entry using the .map
function and gather them in a result list.
public static void main(String[] args) {
List<Map<String, String>> input = new ArrayList<>();
Map<String, String> map = new HashMap<>();
map.put("AddressField", "AddressUsageType");
map.put("AddressValue", "PRINCIPAL");
input.add(map);
map = new HashMap<>();
map.put("AddressField", "StreetNumber");
map.put("AddressValue", "2020");
input.add(map);
map = new HashMap<>();
map.put("AddressField", "StreetName");
map.put("AddressValue", "Some street");
input.add(map);
map = new HashMap<>();
map.put("AddressField", "AddressUsageType");
map.put("AddressValue", "NOT_PRINCIPAL");
input.add(map);
List<String> collect = input.stream().filter(e -> e.get("AddressField").equals("AddressUsageType"))
.map(e -> e.get("AddressValue")).collect(Collectors.toList());
System.out.println(input);
System.out.println(collect);
}
The output is
[{AddressField=AddressUsageType, AddressValue=PRINCIPAL}, {AddressField=StreetNumber, AddressValue=2020}, {AddressField=StreetName, AddressValue=Some street}, {AddressField=AddressUsageType, AddressValue=NOT_PRINCIPAL}]
[PRINCIPAL, NOT_PRINCIPAL]
Upvotes: 2
Reputation: 321
Your usage of Maps is a bit odd here because your actual key "AddressUsageType" is a value inside the map and every map is just one pair of key and value stored behind static keys. If you can not change that, you could go with something like this:
String key = "AddressUsageType";
String result = "";
for (Map<String,String> map : input)
{
if (map.containsValue(key))
{
result = map.get("AddressValue");
break;
}
}
System.out.println(key + " is " + result);
Upvotes: 2