I have a list of strings and list of objects(SomeObject). Every SomeObject will have a list of other objects(SecondaryObject) and that object will have a string property. I need to check if the string property is in the first list.
List<String> stringList = new ArrayList<>(Arrays.asList("String1", "String2"));
List<SomeObject> objectList;
public class SomeObject {
public List<SecondaryObject> secondaryList;
}
public class SecondaryObject {
public String str;
}
for (String mainString : stringList) {
for (SomeObject obj : objectList) {
List<SecondaryObject> secobjList = obj.getSecList();
for (SecondaryObject secObj : secObjList) {
if (secObj.str.equals(mainString)) {
log.log("Found a match");
}
}
}
}
Is there any optimal solution than this.
I would suggest you to make use of hashing. Make a hashMap of stringList then you don't need a third loop. Instead for every secObj's string property just try to get it's value from map, if it does'nt return null then your match is found.
HashMap<String, Integer> map = new HashMap<String, Integer>();
for(String mainString: stringList){
map.put(mainString, 1);
}
for (SomeObject obj : objectList) {
List<SecondaryObject> secobjList = obj.getSecList();
for (SecondaryObject secObj : secObjList) {
if (map.get(secObj.str) != null) {
log.log("Found a match");
}
}
}
From O(n^3) reduced to O(n^2)
If you are not sure if the string property inside any SecondaryObject is unique across the list of SecondaryObject inside SomeObject then I would suggest starting by collating that String in a Set.
The goal is to transform this problem of finding the intersection of two lists of strings.
Then this problem can be solved in two ways
Iterate through the stringList and search for that string in the other list. If you sort that list first the searching can be faster
This is an optimization to approach 1 where you both the lists and then use the longest common subsequence algorithm (https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)
Related
public List<String> findItinerary(List<List<String>> tickets) {
// creating adjencency list
for(String[] ticket : tickets)
{
map.putIfAbsent( ticket[0] ,new PriorityQueue<String>());
map.get(ticket[0]).add(ticket[1]);
}
dfs("JKF");
return path;
}
I m trying to create the adjacency list here, but having problem to iterate through list inside the tickets. I was using for each loop , and coming across this error "List cannot be converted to String[]
for(String[] ticket : tickets)"
You are using String[] where you should be using List<String>. Change your code to this:
for(List<String> ticket : tickets)
{
map.putIfAbsent(ticket.get(0), new PriorityQueue<String>());
map.get(ticket.get(0)).add(ticket.get(1));
}
Update
If you want to convert the List<String> in an array use this snippet:
String[] array = new String[ticket.size()];
ticket.toArray(array); // fill the array
I would suggest this way.
use computeIfAbsent which puts the value in for the key.
then it returns either the existing value or the one just entered.
then there is no need to lookup the key for insertion
public List<String> findItinerary(List<List<String>> tickets) {
// creating adjencency list
for(List<String> ticket : tickets) {
map.computeIfAbsent( ticket.get(0), v->new PriorityQueue<String>())
.add(ticket.get(1));
}
dfs("JKF");
return path;
}
As far as returning path I don't see it defined anywhere.
I want to compare keys of two different arraylists say
List<DataSt> list1 = new ArrayList<DataSt>();
List<DataSt> list2= new ArrayList<DataSt>();
DataSt is:
public class DataSt {
public String key;
BigDecimal time;
BigDecimal memory;
public DataSt(String key,BigDecimal time, BigDecimal memory)
{
this.key=key;
this.time=time;
this.memory=memory;
}
}
list1:
<org.openjdk.jmh.samples.JMHSortBenchmark.collectionsSort,6691.679,5454>
<org.openjdk.jmh.samples.JMHSortBenchmark.abcdSort,5151.45,54545>
<org.openjdk.jmh.samples.JMHSortBenchmark.saasSort,5454.54,21212.2>
<org.openjdk.jmh.samples.JMHSortBenchmark.xyzSort,888.22,2115>
list2:
<org.openjdk.jmh.samples.JMHSortBenchmark.xyzSort,7448.362,7887.2>
<org.openjdk.jmh.samples.JMHSortBenchmark.abcdSort,951.5,4512.5>
<org.openjdk.jmh.samples.JMHSortBenchmark.lmnSort,4454.54,455.2>
And if they match eg., "org.openjdk.jmh.samples.JMHSortBenchmark.xyzSort" so I want to return the <Key,time,memory> of both list1 and list2 i.e., it must return
org.openjdk.jmh.samples.JMHSortBenchmark.xyzSort,888.22,2115
org.openjdk.jmh.samples.JMHSortBenchmark.xyzSort,7448.362,7887.2
org.openjdk.jmh.samples.JMHSortBenchmark.abcdSort,5151.45,54545
org.openjdk.jmh.samples.JMHSortBenchmark.abcdSort,951.5,4512.5
because I want to process the difference between their values and compare them i.e., 888.2,2115 in list1 and 7448.362,7887.2 in map2 thereby logging the difference to a csv file.
I used the following code:
public static List<DataSt> outputComparator(List<DataSt> list1, List<DataSt> list2) {
List<DataSt> map4 = new ArrayList<DataSt> ();
for (DataSt entry: list1) {
if (list2.contains(entry.key)) {
saveRecord(entry, **//Here I want to return DataSt of list2//**,entry.key,map4);
} else {
saveRecord(entry.key, map4);
}
}
for (DataSt entry: list2) {
if (!(list1.contains(entry.key))) {
saveRecord(entry.key, map4);
}
}
return map4;
}
The "entry" in statement "saverecord" returns "list1.key, list1.time, list1.value" for that run
Here I am not sure how to get "DataSt part of list2". Can someone help me how do I retrive "list2.key, list2.time, list2.value" when "list1.key == list2.key" (Refer commented field in saveRecord()).
list2.contains(entry.key) doesn't do what you think it does. It has no idea that DataSt.key is actually a key. You are trying to match a String object to a DataSt object (which will never work).
You could override equals to just compare the keys or you could write your own DataSt findItem(ArrayList<DataSt> list, String key)
If you really need keyed data you could look into a different structure where you can actually lookup by key.
I'm trying to return keys and values through an array method.
I have done this:
public ArrayList<String> translationList() {
for (String key : translations.keySet()) {
System.out.println(key + " = ");
}
return new ArrayList<String>(this.translations.values());
}
And in my Main.java
ArrayList<String> translations = dictionary.translationList();
for (String translation : translations) {
System.out.println(translation);
}
It returns
apina =
cembalo =
banaani =
monkey
harpsichord
banana
I'm not sure how to get them to print on the same line after the translation of the word. I know it's printing the for loop before returning the array but that is where my problem is and not sure how to solve it.
Since you are getting only values back there is no way to get key based on value. So hence not possible.
What you can do is return keys from method and iterate that in your method.
or simply change your method to
public ArrayList<String> translationList() {
List<String> returnList = new ArrayList<>(String);
for (Entry<Integer, String> entry : testMap.entrySet()) {
returnList.add(entry.getKey()+"="+entry.getValue());
}
return returnList;
}
and in your main method
ArrayList<String> translations = dictionary.translationList();
for (String translation : translations) {
System.out.println(translation);
}
I'm really stucked on this problem. I'm not sure if this logic is possible, is there any other whay to achieve what I want?
I'm creating a HashMap like this.
List<String> data1 = new ArrayList();
data1.add("valid1");
data1.add("valid2");
List<String> data2 = new ArrayList();
data2.add("valid3");
data2.add("valid4");
Map<String,ArrayList> hashList = new HashMap();
hashList.put("one",data1);
hashList.put("two",data2);
So the Output will be like this:
{one=[valid1,valid2], two=[valid3,valid4]}
But what am I doing is, i'm reading a file and compare it to hashmap
Code:
String line;
String[] token;
try {
LineIterator it = FileUtils.lineIterator(file,"UTF-8");
while(it.hasNext()){
line = it.nextLine();
token = StringUtils.split(line,(","));
if(token[1].equalsIgnoreCase( //check if its equal to the value of the hashmap){
System.out.println("Valid");
}
}
}
my file looks like this :
test1,valid1,check1
test2,valid3,check2
So what I want to do is, to check if the "token[1]" is valid to the value of hashmap.
Thank you in advance!
Convert the map to list
List<String> list = new ArrayList<String>(map.values());
Then use
list.contains(token[1])
to check if its equal to the list content which is the value of the hashmap
ArrayList<String> check;
check = your_hash_map.get(token[1]);
if(check != null){System.out.println("Valid");}
If you want to get the valid key for the token, the most expensive way of achieving your goal is iterating over the hash keys than iterating over the array value for that key and check if any string inside it matches your conditional.
It should looks like this:
String getValidKey(String token, Map<String, List<String>> hashList) {
for (String key: hashList.keySet()) {
for (String valid: hashList.get(key)) {
if (valid.equalsIgnoreCase(token)) {
return key;
}
}
}
return null;
}
If you only need to know if the token is valid or not this should be enough:
boolean isValid(String token, Map<String, List<String>> hashList) {
for (List<String> list: hashList.values()) {
for (String valid: list) {
if (valid.equalsIgnoreCase(token)) {
return true;
}
}
}
return false;
}
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;
}