How to avoid duplicates in List<Map<String, String>>? - java

I am having List<Map<String, String>> testList =new ArrayList<Map<String, String>>(); this way.
I want to eleminate the duplicate maps out of the list based on first 5 keys, last 2 keys are optional.
I tried using linkedhashset it worked fine, but this code is legacy code which has lot of comparators used and i cannot change that and use set.
Set<Map<String, String>> testList = new LinkedHashSet<Map<String, String>>();
ListOfMaps.java
public class ListOfMaps {
Map<String,String> map = new HashMap<String,String>();
List<Map<String, String>> testList =new ArrayList<Map<String, String>>();
public static void main(String[] args) {
ListOfMaps ll = new ListOfMaps();
ll.test();
}
public void test()
{
map = new HashMap<String,String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "30");
map.put("gender", "M");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
testList.add(map);
map = new HashMap<String,String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "31");
map.put("gender", "F");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
testList.add(map);
//This map object has duplicate keys year,standrad,age,gender,class same as like first map object .
//so this object should be ignore while adding into list.
//marks and score score keys are optional and need not to be verified.
map = new HashMap<String,String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "30");
map.put("gender", "M");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
testList.add(map);
System.out.println(testList.toString());
}
}
Can anyone help me in this issue?
Thanks

Having bad design it is hard to solve your problem. Here one way to solve your problem using extra Person class maintaining your legacy code.
public class ListOfMaps {
Map<String, String> map = new HashMap<String, String>();
List<Map<String, String>> testList = new ArrayList<Map<String, String>>();
Set<Person> st = new HashSet<>();
/**
* #param args
*/
public static void main(String[] args) {
ListOfMaps ll = new ListOfMaps();
ll.test();
}
public void test() {
map = new HashMap<String, String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "30");
map.put("gender", "M");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
if (st.add(new Person(map)))
testList.add(map);
map = new HashMap<String, String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "31");
map.put("gender", "F");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
if (st.add(new Person(map)))
testList.add(map);
// This map object has duplicate keys year,standrad,age,gender,class
// same as like first map object .
// so this object should be ignore while adding into list.
// marks and score score keys are optional and need not to be verified.
map = new HashMap<String, String>();
map.put("year", "2015");
map.put("standrad", "second");
map.put("age", "30");
map.put("gender", "M");
map.put("class", "first");
map.put("marks", "100");
map.put("score", "200");
if (st.add(new Person(map)))
testList.add(map);
System.out.println(testList.toString());
}
}
class Person {
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((cls == null) ? 0 : cls.hashCode());
result = prime * result + ((gender == null) ? 0 : gender.hashCode());
result = prime * result
+ ((standard == null) ? 0 : standard.hashCode());
result = prime * result + ((year == null) ? 0 : year.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Person)) {
return false;
}
Person other = (Person) obj;
if (age == null) {
if (other.age != null) {
return false;
}
} else if (!age.equals(other.age)) {
return false;
}
if (cls == null) {
if (other.cls != null) {
return false;
}
} else if (!cls.equals(other.cls)) {
return false;
}
if (gender == null) {
if (other.gender != null) {
return false;
}
} else if (!gender.equals(other.gender)) {
return false;
}
if (standard == null) {
if (other.standard != null) {
return false;
}
} else if (!standard.equals(other.standard)) {
return false;
}
if (year == null) {
if (other.year != null) {
return false;
}
} else if (!year.equals(other.year)) {
return false;
}
return true;
}
String year, standard, age, gender, cls, marks, score;
public Person(String year, String standard, String age, String gender,
String cls, String marks, String score) {
this.year = year;
this.standard = standard;
this.age = age;
this.gender = gender;
this.cls = cls;
this.marks = marks;
this.score = score;
}
public Person(Map<String, String> map) {
this.year = map.get("year");
this.standard = map.get("standrad");
this.age = map.get("age");
this.gender = map.get("gender");
this.cls = map.get("class");
this.marks = map.get("marks");
this.score = map.get("score");
}
}

Related

Split String based on delimiter and convert to n level Pair of Pair based on count of delimiter

There is a hashmap and below is the requirement :
Map<String, Object> objectmetainfo = new HashMap();
objectmetainfo.put("userdetails.info.metadata.user.home.address.details", "address");
objectmetainfo.put("userdetails.info.metadata.user.id", "id");
objectmetainfo.put("userdetails.info.metadata.userSupervisor.id", "id");
objectmetainfo.put("info.metadata.code", "code");
objectmetainfo.put("zip", "zip");
Get all the records of hashmap and iterate it
Split the Key based on delimiter and convert it to Pair or Hashmap
The number of delimiter will vary in each string
Below should be the output :
E.g.: For "userdetails.info.metadata.user.home.address.details", "address", below output is required
HashMap<userdetails, HashMap<info, HashMap<metadata, HashMap<user, HashMap<home, HashMap<address, Map<details, address>>>>>>>
or Pair<String, Object> pair = new Pair("userdetails", new Pair("info", new Pair("metadata", new Pair("user", new Pair("home", new Pair("address", new Pair("details", "addressvalue")))))));
Assuming your string won't be crazy long this would work, otherwise you'd get a StackOverflow error.l
I did this using a recursive approach
Split keys by "."
Convert them to the list iterator
Iterate this list recursively to create a nested map
At the end of recursion put the value from objectmetainfo map.
Create an empty result map and recursively merge all the results.
Code:
import java.util.*;
public Map<String, Object> nestedMaps(Iterator<String> keys, String value) {
if (keys.hasNext()) {
String key = keys.next();
Map<String, Object> nestMap = nestedMaps(keys, value);
Map<String, Object> map = new HashMap<>();
map.put(key, nestMap);
if (Objects.equals(nestMap, null))
map.put(key, value);
return map;
}
return null;
}
public void mergeNested(Object srcObj, Object targetObj) {
if (srcObj instanceof Map && targetObj instanceof Map) {
Map<String, Object> srcMap = (Map<String, Object>) srcObj;
Map<String, Object> targetMap = (Map<String, Object>) targetObj;
for (String targetKey : targetMap.keySet()) {
if (srcMap.containsKey(targetKey)) {
mergeNested(srcMap.get(targetKey), targetMap.get(targetKey));
} else {
srcMap.putAll(targetMap);
}
}
}
}
public Map<String, Object> objectmetainfo = new LinkedHashMap<>();
objectmetainfo.put("userdetails.info.metadata.user.home.address.details", "addressValue");
objectmetainfo.put("userdetails.info.metadata.user.id", "id");
objectmetainfo.put("userdetails.info.metadata.userSupervisor.id", "id");
objectmetainfo.put("info.metadata.code", "code");
objectmetainfo.put("zip", "zip");
public Map<String, Object> result = new HashMap<>();
for (Map.Entry<String, Object> e : objectmetainfo.entrySet()) {
List<String> keys = new ArrayList<>(Arrays.asList(e.getKey().split("\\.")));
Map<String, Object> nestedMaps = nestedMaps(keys.iterator(), String.valueOf(e.getValue()));
mergeNested(result, nestedMaps);
}
System.out.println(result);
I printed out all the hashmaps using toString method.
Output:
{
zip= zip,
userdetails= {
info= {
metadata= {
userSupervisor= {
id= id
},
user= {
id= id,
home= {
address= {
details= addressValue
}
}
}
}
}
},
info= {
metadata= {
code= code
}
}
}
Below is the modified logic to remove 2nd recursive call, with this method we are passing the objMap as reference and finally we will have the objMap ready with result
Map<String, Object> objMap = new HashMap<>();
for (Map.Entry<String, Object> e : getObjectMetaInfoMap().entrySet()) {
populateMetaDataMap(keys.iterator(), String.valueOf(e.getValue()), objMap, true, StringUtils.EMPTY);
}
public static Map<String, Object> populateMetaDataMap(Iterator<String> keys, String value, Map<String, Object> objMap, boolean newCall, String matchingKey) {
if (keys.hasNext()) {
String key = keys.next();
if(objMap.get(key) != null && objMap.get(key) instanceof Map) {
return populateMetaDataMap(keys, value, (Map<String, Object>) objMap.get(key), newCall, matchingKey );
} else {
if(newCall) {
newCall = false;
matchingKey = key;
}
Map<String, Object> nestMap = populateMetaDataMap(keys, value, objMap, newCall, matchingKey);
Map<String, Object> map = new HashMap<>();
if (Objects.equals(nestMap, null))
map.put(key, value);
else
map.put(key, nestMap);
if(key.equals(matchingKey)) {
if(Objects.equals(nestMap, null)) {
objMap.put(key, value);
} else {
objMap.put(key, nestMap);
}
}
return map;
}
}
return null;
}

How to retrieve tables which exists in a pdf using AWS Textract in java

I found article below to do in python.
https://docs.aws.amazon.com/textract/latest/dg/examples-export-table-csv.html
also I used article below to extract text.
https://docs.aws.amazon.com/textract/latest/dg/detecting-document-text.html
but above article helped to get only text, I also used function "block.getBlockType()"
of Block but none of block returned its type as "CELL" even tables are there in image/pdf.
Help me found java library similar to "boto3" to extract all tables.
What I did, I created models of each dataset in the json response and can use this models to build a table view in jsf.
public static List<TableModel> getTablesFromTextract(TextractModel textractModel) {
List<TableModel> tables = null;
try {
if (textractModel != null) {
tables = new ArrayList<>();
List<BlockModel> tableBlocks = new ArrayList<>();
Map<String, BlockModel> blockMap = new HashMap<>();
for (BlockModel block : textractModel.getBlocks()) {
if (block.getBlockType().equals("TABLE")) {
tableBlocks.add(block);
}
blockMap.put(block.getId(), block);
}
for (BlockModel blockModel : tableBlocks) {
Map<Long, Map<Long, String>> rowMap = new HashMap<>();
for (RelationshipModel relationship : blockModel.getRelationships()) {
if (relationship.getType().equals("CHILD")) {
for (String id : relationship.getIds()) {
BlockModel cell = blockMap.get(id);
if (cell.getBlockType().equals("CELL")) {
long rowIndex = cell.getRowIndex();
long columnIndex = cell.getColumnIndex();
if (!rowMap.containsKey(rowIndex)) {
rowMap.put(rowIndex, new HashMap<>());
}
Map<Long, String> columnMap = rowMap.get(rowIndex);
columnMap.put(columnIndex, getCellText(cell, blockMap));
}
}
}
}
tables.add(new TableModel(blockModel, rowMap));
}
System.out.println("row Map " + tables.toString());
}
} catch (Exception e) {
LOG.error("Could not get table from textract model", e);
}
return tables;
}
private static String getCellText(BlockModel cell, Map<String, BlockModel> blockMap) {
String text = "";
try {
if (cell != null
&& CollectionUtils.isNotEmpty(cell.getRelationships())) {
for (RelationshipModel relationship : cell.getRelationships()) {
if (relationship.getType().equals("CHILD")) {
for (String id : relationship.getIds()) {
BlockModel word = blockMap.get(id);
if (word.getBlockType().equals("WORD")) {
text += word.getText() + " ";
} else if (word.getBlockType().equals("SELECTION_ELEMENT")) {
if (word.getSelectionStatus().equals("SELECTED")) {
text += "X ";
}
}
}
}
}
}
} catch (Exception e) {
LOG.error("Could not get cell text of table", e);
}
return text;
}
TableModel to create the view from:
public class TableModel {
private BlockModel table;
private Map<Long, Map<Long, String>> rowMap;
public TableModel(BlockModel table, Map<Long, Map<Long, String>> rowMap) {
this.table = table;
this.rowMap = rowMap;
}
public BlockModel getTable() {
return table;
}
public void setTable(BlockModel table) {
this.table = table;
}
public Map<Long, Map<Long, String>> getRowMap() {
return rowMap;
}
public void setRowMap(Map<Long, Map<Long, String>> rowMap) {
this.rowMap = rowMap;
}
#Override
public String toString() {
return table.getId() + " - " + rowMap.toString();
}
I have something similar:
public class AnalyzeDocument {
public DocumentModel startProcess(byte[] content) {
Region region = Region.EU_WEST_2;
TextractClient textractClient = TextractClient.builder().region(region)
.credentialsProvider(EnvironmentVariableCredentialsProvider.create()).build();
return analyzeDoc(textractClient, content);
}
public DocumentModel analyzeDoc(TextractClient textractClient, byte[] content) {
try {
SdkBytes sourceBytes = SdkBytes.fromByteArray(content);
Util util = new Util();
Document myDoc = Document.builder().bytes(sourceBytes).build();
List<FeatureType> featureTypes = new ArrayList<FeatureType>();
featureTypes.add(FeatureType.FORMS);
featureTypes.add(FeatureType.TABLES);
AnalyzeDocumentRequest analyzeDocumentRequest = AnalyzeDocumentRequest.builder().featureTypes(featureTypes)
.document(myDoc).build();
AnalyzeDocumentResponse analyzeDocument = textractClient.analyzeDocument(analyzeDocumentRequest);
List<Block> docInfo = analyzeDocument.blocks();
// util.displayBlockInfo(docInfo);
PageModel pageModel = util.getTableResults(docInfo);
DocumentModel documentModel = new DocumentModel();
documentModel.getPages().add(pageModel);
Iterator<Block> blockIterator = docInfo.iterator();
while (blockIterator.hasNext()) {
Block block = blockIterator.next();
log.debug("The block type is " + block.blockType().toString());
}
return documentModel;
} catch (TextractException e) {
System.err.println(e.getMessage());
}
return null;
}
and this is the util file:
public PageModel getTableResults(List<Block> blocks) {
List<Block> tableBlocks = new ArrayList<>();
Map<String, Block> blockMap = new HashMap<>();
for (Block block : blocks) {
blockMap.put(block.id(), block);
if (block.blockType().equals(BlockType.TABLE)) {
tableBlocks.add(block);
log.debug("added table: " + block.text());
}
}
PageModel page = new PageModel();
if (tableBlocks.size() == 0) {
return null;
}
int i = 0;
for (Block table : tableBlocks) {
page.getTables().add(generateTable(table, blockMap, i++));
}
return page;
}
private TableModel generateTable(Block table, Map<String, Block> blockMap, int index) {
TableModel model = new TableModel();
Map<Integer, Map<Integer, String>> rows = getRowsColumnsMap(table, blockMap);
model.setTableId("Table_" + index);
for (Map.Entry<Integer, Map<Integer, String>> entry : rows.entrySet()) {
RowModel rowModel = new RowModel();
Map<Integer, String> value = entry.getValue();
for (int i = 0; i < value.size(); i++) {
rowModel.getCells().add(value.get(i));
}
model.getRows().add(rowModel);
}
return model;
}
private Map<Integer, Map<Integer, String>> getRowsColumnsMap(Block block, Map<String, Block> blockMap) {
Map<Integer, Map<Integer, String>> rows = new HashMap<>();
for (Relationship relationship : block.relationships()) {
if (relationship.type().equals(RelationshipType.CHILD)) {
for (String childId : relationship.ids()) {
Block cell = blockMap.get(childId);
if (cell != null) {
int rowIndex = cell.rowIndex();
int colIndex = cell.columnIndex();
if (rows.get(rowIndex) == null) {
Map<Integer, String> row = new HashMap<>();
rows.put(rowIndex, row);
}
rows.get(rowIndex).put(colIndex, getText(cell, blockMap));
}
}
}
}
return rows;
}
public String getText(Block block, Map<String, Block> blockMap) {
String text = "";
if (block.relationships() != null && block.relationships().size() > 0) {
for (Relationship relationship : block.relationships()) {
if (relationship.type().equals(RelationshipType.CHILD)) {
for (String childId : relationship.ids()) {
Block wordBlock = blockMap.get(childId);
if (wordBlock != null && wordBlock.blockType() != null) {
if (wordBlock.blockType().equals(BlockType.WORD))) {
text += wordBlock.text() + " ";
}
}
}
}
}
}
return text;
}

How to decrease the time complexity of this O(n^3) code

Here is the piece of code that's bothering me. It does the task but I want to optimize it if possible.
I have list of Entities
Config for each Entity based on ID.
From Config has Tips for each Entity
From Config has Rejects for each Entity
Rejects have ID for each Tip
I get ID of Tip to be reject, remove it from allItems and add it to removeItems
Map<String, String> removeItems = new HashMap<>();
Map<String, Pair<String, Config>> allItems = new HashMap<>();
for(final Entity entity : entities) {
final Config config = Configs
.get(entity.getId());
if (config == null || entity.getTxId() == null) {
continue;
}
if (config.getTips() != null) {
for (final Tip tip : config.getTips()) {
String currentId = entity.getId();
String currentTipId = tip.getTipId();
if(allItems.containsKey(currentTipId)) {
Pair<String, Config> item = allItems.get(currentTipId);
if(tip.getPriority() > item.getValue().getPriority()) {
removeItems.put(currentTipId, item.getKey());
allItems.put(currentTipId, new Pair(currentId, tip));
} else {
removeItems.put(currentTipId, currentId);
}
} else {
allItems.put(currentTipId, new Pair(currentId, tip));
}
List<String> rejects = tip.getRejects();
if(CollectionUtils.isEmpty(rejects)) {
continue;
}
for (String reject : rejects) {
Pair<String, Config> pair = allItems.get(reject);
if (null != pair) {
String rejectId = pair.getKey();
if (StringUtils.isNotEmpty(rejectId)) {
removeItems.put(reject, rejectId);
}
}
}
}
}
}

Get values from below string using regex in java

I am a beginner to regex.
I have below String:
fail:2,success:1,fetch:1
Output Map: Get Map which contains all key-values as below:
fail - 2 (key=fail, value=2)
success - 1
fetch - 1
I have tried using below solution:
public static void main(String arg[]) {
String msg = "fail:1,success:1,policyfetch:1";
System.out.println(getKeyValuesFromMsg(msg));
}
public static Map getKeyValuesFromMsg(String msg) {
if (msg != null) {
Map keyvalues = new HashMap();
Pattern p = Pattern.compile("(\\w+):(,+)");
Matcher m = p.matcher(msg);
while (m.find()) {
keyvalues.put(m.group(1), m.group(2));
}
return keyvalues;
} else
return Collections.emptyMap();
}
You can use the split function, The following snippet should work fine
Map<String,String> map = new HashMap();
String str = "fail:2,success:1,fetch:1";
String[] keyValueParts = str.split(",");
for(String s : keyValueParts){
String parts[] = s.split(":");
map.put(parts[0],parts[1]);
}
System.out.println(map);
i would have used below method for the same.
public static void main(String arg[]) {
String msg = "fail:1,success:1,policyfetch:1";
System.out.println(getKeyValuesFromMsg(msg));
}
private static Map<Object, Object> getKeyValuesFromMsg(String msg) {
Map<Object,Object> mapObj = new HashMap<Object,Object>();
for (int i=0;i<msg.split(",").length;i++)
mapObj.put(msg.split(",")[i].split(":")[0],msg.split(",")[i].split(":")[1]);
return mapObj;
}
my solution:
public static Map<String, Integer> trans2Map(String source) {
if (null == source) {
return Collections.emptyMap();
}
Map<String, Integer> result = new HashMap<>();
Arrays.stream(source.split(","))
.filter(pair -> pair.split(":").length == 2)
.forEach(pair -> {
String key = pair.split(":")[0];
Integer value;
try {
value = Integer.parseInt(pair.split(":")[1]);
} catch (Exception e) {
return;
}
result.put(key, value);
});
return result;
}

Performance Issue with Java Code

I am using java with mongodb.. I am getting performance issue in this below code can you please optimize this code?
I need to increase the performance of this function.
//first function which receives the parameter as associationId. can you guys please help me to increase the performance for this function..
public ArrayList<ResidentAssociationMapEntity> listUsersByAssociation(String
associationId) {
HashMap<String, Object> filterExpressions = new HashMap<String, Object>();
filterExpressions.put("associationId", associationId);
filterExpressions.put("residentStatus", 1);
List<ResidentAssociationMapEntity> residents =
DBManager.getInstance().getByMultipleFields(
ResidentAssociationMapEntity.class, filterExpressions);
if (residents != null && residents.size() > 0) {
for (ResidentAssociationMapEntity map : residents ) {
map.setUser(getUser(map.getUserId()));
}
}
return new ArrayList<ResidentAssociationMapEntity>(residents);
}
// get user function
public UserEntity getUser(String userId) {
UserEntity entity = DBManager.getInstance().getById(UserEntity.class,
userId);
ResidentAssociationMapEntity map =
getResidentAssocaitionMap(entity.getUserId());
if (map != null) {
entity.setUnitNo(map.getUnitNumber() + "");
entity.setAssociationId(map.getAssociationId());
entity.setAssociationName(CompanyDAO.getInstance().getCompany(map.getAssocia
tionId()).getName());
}
return entity;
}
//getResidentAssocaitionMap function
private ResidentAssociationMapEntity getResidentAssocaitionMap(String
residentId) {
HashMap<String, Object> filterExpressions = new HashMap<String, Object>();
filterExpressions.put("userId", residentId);
filterExpressions.put("residentStatus", 1);
List<ResidentAssociationMapEntity> residents =
DBManager.getInstance().getByMultipleFields(
ResidentAssociationMapEntity.class, filterExpressions);
if (residents != null && residents.size() > 0) {
return residents.get(0);
}
return null;
}

Categories