Hashmap holding a hashset - how to retrieve data - java

How do I obtain a list of all the objects that have the same value for a specific attribute out of HashMap<String,HashSet<String>> objects the String holds the attributes and the HashSet holds the list of values for the attributes!

Map<String,Set<String>> objects = new HashMap<String,Set<String>>();
// fill it up
String needle = "value";
List<String> results = new LinkedList<String>();
for(Map.Entry<String,Set<String>> entry : objects.entry set())
{
if(entry.getValue().contains(needle))
{
results.add(entry.getKey());
}
}
return results;

Related

Push values to a map when key is already exisitng in a map

I have declared a map as below:
Map<String, String[]> test = new HashMap<String, String[]>();
I have a variable empnames which is an array and deptname is a String and i have declared the deptname and empnames as below:
String deptname = ['Department']
String empnames = [['Test1']['Test2']]
if (deptname != null)
{
if (test.containsKey(deptname))
{
///
}
else
{
test.put(deptname, new String[]{empnames});
}
}
If the test map already contains deptname key then what condition i should write in if condition to append new values to department?
Since you tagged for [grails], I assume a Groovy answer is appropriate too. You can use a Map with .withDefault{ ... } to provide the content in case the key is missing. E.g.
def data = [["x", ["a", "b"]], ["x", ["c", "d"]]]
def test = [:].withDefault{[]} // XXX
data.each{ k, vs ->
test[k].addAll(vs) // if there is no key `k`, create an empty array, so `.addAll` just works
}
println(test.inspect())
// => ['x':['a', 'b', 'c', 'd']]
You can use the new methods in Java 8 like putIfAbsent to add new entry if key is not present and computeIfPresent to append values to an existing key of a map.
An example would be:
public static void main(String[] args) {
Map<String, String[]> test = new HashMap<>();
String deptname = "Department";
String[] empnames = {"Test1", "Test2"};
if (deptname != null){
test.putIfAbsent(deptname, empnames);
test.computeIfPresent(deptname, (dept, value) -> {
List<String> list = new ArrayList<>(Arrays.asList(value));
list.add("Test3");
value = list.toArray(value);
return value;
});
}
for(String s : test.get("Department")){
System.out.println(s);
}
}
Here the putIfAbsent tests if the key is present, if not adds a new key-value entry. The computeIfAbsent on the other hand tests if the key is present, if yes it computes the new value for the existing key-value entry.
The output of the above code is:
Test1
Test2
Test3
This is because initially the key Department was not present in the map test, so it was added to it along with the value empnames as an array.
In the second operation the method computeIfPresent checked that the key Department was already in the map so it appended the new String Test3 to existing value array of [Test1, Test2].
The same can be done for an List instead of an array:
public static void main(String[] args) {
Map<String, List<String>> test = new HashMap<>();
String deptname = "Department";
List<String> empnames = new ArrayList(Arrays.asList("Test1", "Test2"));
if (deptname != null){
test.putIfAbsent(deptname, empnames);
test.computeIfPresent(deptname, (dept, value) -> {
value.add("Test3");
return value;
});
}
for(String s : test.get("Department")){
System.out.println(s);
}
}
ArrayList<String> departmentList;
if(test.containsKey(key)){
// if the key has already been used, then and add a new value to it
list = test.get(key);
list.add(value);
test.put(key, list);
} else {
// if the key hasn't been used yet, then create a new ArrayList<String> object, add the value
list = new ArrayList<String>();
list.add(value);
test.put(key, list);
}
As others have suggested, this would be easier if you had an ArrayList instead of String[].
But since you have a String[], you will have to make a new array of old_array's_size + list_to_add and copy over the values from the old array into the new one plus the new value you want to append.
So inside of your if statement:
String [] oldList = test.get(deptName);
String[] newList = new String[oldList.length + empnames.length]; //Make a new array with enough space for the previous values at deptname but also the new ones you want to add
//Put all of the values from the existing value at deptname into a new array
for (int i = 0; i < oldList.length; i++)
newList[i] = oldList[i];
//Put all of the values from the list of values you want to add into the new array
for (int i = 0; i < empnames.length; i++)
newList[oldList.length + i] = empnames[i];
test.put(deptname, newList); //Put the completed list back into the map
Again, if you used some kind of List this would be easier. One good reason besides being able to append is that you can easily sort it alphabetically using Collections.sort.

Access Values from an ArrayList That is inside another ArrayList

java.util.List records = new java.util.ArrayList();
java.sql.ResultSet rs = selectestatement.executeQuery(query1);
while (rs.next()) {
java.util.List record = new java.util.ArrayList();
record.add(rs.getString("WHLO").trim());
record.add("888509018579");
record.add(rs.getString("ITEM_CODE").trim());
record.add(rs.getString("ARRIVAL_DATE").trim());
record.add(rs.getString("PAIRS_PER_CASE").trim());
record.add(rs.getString("ATS").trim());
records.add(record);
}
In this code, Final arraylist is the "records array". This records arraylist contents few record arrays.
How can i access the 1st element of record arraylist from the records arraylist?
Don't use raw types:
List<List<String>> records = new ArrayList<>();
List<String> record = new ArrayList<>();
...
records.add(record);
This way records.get(i) will return a List<String> instead of an Object, so you can access the elements of the inner List:
String first = records.get(0).get(0);
What you really want is a class containing your row data.
class RecordData {
public String whlo;
public long someNumber = 888509018579;
public String itemCode;
public String arrivalDate;
public String pairsPerCase;
public String ats;
}
and then do
java.util.List<RecordData> records = new java.util.ArrayList<>();
while (rs.next()) {
RecordData record = new RecordData();
record.whlo = rs.getString("WHLO").trim();
record.itemCode = rs.getString("ITEM_CODE").trim();
record.arrivalDate = rs.getString("ARRIVAL_DATE").trim();
record.pairsPerCase = rs.getString("PAIRS_PER_CASE").trim();
record.ats = rs.getString("ATS").trim();
records.add(record);
}
In fact, you want to make the members private and accessible via getters and setters, and use LocalDate for the arrivalDate and int for the pairsPerCase member, but the first point is not using a List to store the retrieved values but wrap it in a business-oriented class.
You can do something like this
((ArrayList)records.get(0)).get(0) to access the first element of the array list that is in the first position of the records array list.
Please note that if you specify what does the records contains (in this case records will contains array lists) then you won't need to cast the element to array list.
List<List<String>> records = new ArrayList<ArrayList>();
{...}
records.get(0).get(0); //You don't need the cast because Java already knows that what it is inside records are Lists

How to you sort and then make an unmodifiable of type HashMap<String, HashMap<Path, HashSet<Integer>>>?

I am building an inverted index in Java. I already have the structure populated with data from files read. Now I want sort all three levels of the structure and then create an unmodifiable copy of it to return to another class for writing it to a file. Ideally I could use the Collections.sort() and the Collections.unmodifiableSet() / Collections.unmodifiableMap() functions. And no, I do not want to use a TreeSet.
Current code:
public HashMap<String, HashMap<Path, HashSet<Integer>>> getInvertedIndex()
{
// sortInvertedIndex();
HashMap<String, HashMap<Path, HashSet<Integer>>> copyOfInvertedIndex = null;
// Set<String> words = invertedIndex.keySet();
Set<Entry<String, HashMap<Path, HashSet<Integer>>>> m = invertedIndex.entrySet();
// copyOfInvertedIndex = Collections.unmodifiableMap(invertedIndex);
return copyOfInvertedIndex;
}
public void sortInvertedIndex()
{
// List words = new List();
// Collections.addAll(words, invertedIndex.keySet());
// invertedIndex.keySet();
// // SortedSet<String> keys = new TreeSet<String>(myHashMap.keySet());
// // SortedSet<String> values = new
// TreeSet<String>(myHashMap.values());
// Collections.sort(list);
}

how to get duplicated and non duplicated element of arrayList?

I have an object as Riziv with three variables as id, cnk and product. Then I search in a databank for this object and add it to a ArrayList as ArrayList<Riziv> list.
Now I should checkout if all object in his array are the same cnk then return true otherwise I should return all objects which are not the same cnk with error message.
public class Riziv{ String id, cnk, product; }
ArrayList<Riziv> list = getArrayListFromDatabank(id);
public void getDuplicatedWhichHasTheSameCnk(){
}
}
Using standard JVM structures (MultiMap is provided by guava), you can do that:
public List<Riviz> getDuplicates(final List<Riviz> l)
{
final HashMap<String, List<Riviz>> m = new HashMap<String, List<Riviz>>();
final List<Riviz> ret = new ArrayList<Riviz>();
String cnk;
for (final Riviz r: l) {
cnk = r.getCnk();
if (!m.contains(cnk))
m.add(cnk, new ArrayList<Riviz>());
m.get(cnk).add(r);
}
List<Riviz> tmp;
for (final Map.Entry<String, List<Riviz>> entry: m.entrySet()) {
tmp = entry.getValue();
if (tmp.size() == 1) // no dups
continue;
ret.addAll(tmp);
}
return ret;
}
ret will contain the duplicates. You can change that function to return a Map<String, Riviz> instead, and filter out entries where the list size is only one. You'll then get a map with the conflicting cnks as keys and a list of dups as values.
I am not clear exactly what you want however I suspect you want something like this.
MultiMap<Key, Riziv> multiMap =
List<Riziv> list =
for(Riziv r: list)
multiMap.put(r.getCnk(), r);
for(Key cnk: multiMap.keySet()) {
Collection<Riziv> sameCnk = multiMap.get(cnk);
// check size and compare entries
}
The multi-map will have the list of Riziv objects for each Cnk.
One way to do it is write a comparator to sort the list by cnk String and then compare each consecutive cnk String to the next, if you find a duplicate, they will be right next to eachother.
1.) Sort the list using a comparator by sorting on the cnk variable.
2.) Compare each element in the list to the next for duplicates.
There's probably many other ways to solve this, this is just the first that came to mind.
I did not test this so you have been forewarned lol:
ArrayList<Riziv> rizArray = new ArrayList<Riziv>();
//Sort the array by the CNK variable.
Collections.sort(rizArray, new Comparator<Riziv>(){
#Override
public int compare(Riziv arg0, Riziv arg1) {
//Return the comparison of the Strings.
//Use .compareToIgnoreCase if you want to ignore upper/lower case.
return arg0.getCnk().compareTo(arg1.getCnk());
}
});
//List should be in alphabetical order at this point.
List<Riziv> duplicates = new ArrayList<Riziv>();
Riziv rizPrevious = null;
for(Riziv riz: rizArray){
if(rizPrevious == null){
rizPrevious = riz;
continue;
}
if(riz.getCnk().compareTo(rizPrevious.getCnk()) == 0){
duplicates.add(riz);
}
rizPrevious = riz;
}

Join two Lists in Java

I need to join two Lists in Java. I've a list which has a VO that has a name and description. I've another list which has same VO type that has name and Address. The "name" is same. I need to create a List with this VO which has both name, address and description.
The VO structure is
public class PersonDetails{
private String name;
private String description;
private String address;
//getters and setters
}
Can someone please suggest me the best way to implement it?
It depends:
If the lists contain both exactly the same data, you can sort them both by name, iterate over them en set the missing property.
If not, I would put the first list in a Map, with the name as key. Then iterate over the second list, look in the map for the VO and set the value.
After that, just get all the value's out of the map again as a List.
public List<Vo> merge(List<Vo> list1, List<Vo> list2) {
Map<String, Vo> tempMap = new HashMap<String, Vo>();
for (Vo v : list1) {
tempMap.put(v.name, v);
}
for (Vo vv : list2) {
//The if is in case the 2 lists aren't filled with the same objects
if (tempMap.containsKey(vv.name)) {
tempMap.get(vv.name).description = vv.description;
} else {
tempMap.put(vv.name, vv);
}
}
return new ArrayList<Vo>(tempMap.values());
}
If the lists contain both EXACT the same VO (equal by name), you can use this.
public List<Vo> merge(List<Vo> list1, List<Vo> list2) {
Collections.sort(list1, new Comparator<Vo>() {
public int compare(Vo o1, Vo o2) {
return o1.name.compareTo(o2.name);
}
});
Collections.sort(list2, new Comparator<Vo>() {
public int compare(Vo o1, Vo o2) {
return o1.name.compareTo(o2.name);
}
});
for(int i = 0; i < list1.size(); i++){
list1.get(i).description = list2.get(i).description;
}
return list1;
}
Put all elements of the first list in a map, then merge the contents of the second list into it:
final List<PersonDetails> listWithAddress =
new ArrayList<PersonDetails>();
final List<PersonDetails> listWithDescription =
new ArrayList<PersonDetails>();
// fill both lists with data
final Map<String, PersonDetails> map =
// map sorted by name, change to HashMap otherwise
// (or to LinkHashMap if you need to preserve the order)
new TreeMap<String, PersonDetails>();
for(final PersonDetails detailsWithAddress : listWithAddress){
map.put(detailsWithAddress.getName(), detailsWithAddress);
}
for(final PersonDetails detailsWithDescription : listWithDescription){
final PersonDetails retrieved =
map.get(detailsWithDescription.getName());
if(retrieved == null){
map.put(detailsWithDescription.getName(),
detailsWithDescription);
} else{
retrieved.setDescription(detailsWithDescription.getDescription());
}
}
I would put each list of the source VO lists in a map by name, create a set of both keys, iterate it and add a target VO to the result list.
In the example code, VO is the target VO, VOD is the source VO with description only, VOA is the source VO with address only:
List<VOD> descriptions = ...;
List<VOA> addresses = ...;
Map<String,String> description ByName = new HashMap<String,String>();
for (VOD description : descriptions) {
descriptionByName.put(description.name, description.description);
}
Map<String,String> addressByName = new HashMap<String,String>();
for (VOA address: addresses ) {
addressByName.put(address.name, address.address);
}
Set<String> allNames = new HashSet<String>();
allNames.addAll(descriptionByName.keySet());
allNames.addAll(addressByName.keySet());
List<VO> result = new ArrayList<VO>();
for (String name : allNames) {
VO one = new VO();
one.name = name;
one.address = addressByName.get(name)
one.description = descriptionByName.get(name)
result.add(one);
}
Go from list to HashMap, use the name string as key. So you can merge you data quite efficient.
List<VO> list = new ArrayList<VO>();
for (VO vo1 : vo1List) {
for (VO vo2 : vo2List) {
if (vo1.getName().equals(vo2.getName())) {
VO newVo = new VO();
newVO.setName(vo1.getName());
newVO.setDescription(vo1.getDescription());
newVO.setAddress(vo2.getAddress);
list.add(newVO);
break;
}
}
}
It's best that you sort both lists on name beforehand, it makes the double iteration faster.

Categories

Resources