I have to check whether an arraylist contains any of the value passed through an object.
Consider an arraylist with values "abc", "jkl","def", "ghi".
And String check="abc,ghi"
We have to check whether any of the value in string (abc or ghi) is present in the arraylist and we can stop checking when a match is found.
Traditionally, we can split the String check with comma and use arraylist.contains() in iteration for each comma separated values.
But this is time consuming. Is there any better way to do this check.
One way would be to use the retainAll method and Sets.
Example
// note an additional "ghi" here
List<String> original = new ArrayList<String>(Arrays.asList(new String[]{"abc", "jkl","def", "ghi", "ghi"}));
Set<String> clone = new HashSet<String>(original);
Set<String> control = new HashSet<String>(Arrays.asList(new String[]{"abc","ghi"}));
clone.retainAll(control);
System.out.println(clone.equals(control));
Output
true
This is still O(n), but you could build a set from the search strings and just iterate over the list once:
HashSet<String> checks = new HashSet<String>();
checks.addAll(Arrays.asList(check.split(",")));
for (String item : arraylist) {
if (checks.contains(item)) {
// Found one
}
}
You could transform check into a regexp and loop only once through the ArrayList.
String check = "abc,ghi";
Pattern p = Pattern.compile("(" + check.replace(',', '|') + ")");
List<String> list = Arrays.asList(new String[] { "abc", "jkl", "def", "ghi" });
for (String element : list) {
if (p.matcher(element).matches()) {
System.out.println("match: " + element);
}
}
Related
I have an arrayList that contains arrays. How do I check if the arrayList contains a specified array? I used .contains method and it returns false instead of expected true.
import java.util.ArrayList;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
action.add(new String[]{"appple", "ball"});
String[] items = new String[]{"appple", "ball"};
if (action.contains(new String[]{"appple", "ball"})) {
System.out.println("Yes");
}
System.out.println(action.contains(items)); // False
}
}
As you are creating different arrays (even if the contents are the same), contains will result false.
However, if you do this:
List<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"apple","ball"};
action.add(items);
if (action.contains(items))
System.out.println("Yes");
This will print Yes.
Also, some examples of the behaviour:
String[] items = new String[]{"apple","ball"};
action.add(items);
String[] clone = items.clone();
String[] mirror = items;
action.contains(clone); // false
action.contains(mirror); // true
items[0]="horse";
System.out.println(mirror[0]); // "horse"
System.out.println(clone[0]); // "apple"
System.out.println(action.get(0)[0]); // "horse"
mirror[1]="crazy";
System.out.println(clone[1]); // "ball"
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
clone[1]="yolo";
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
System.out.println(mirror[1]); // "crazy"
System.out.println(action.get(0).hashCode()); //2018699554
System.out.println(items.hashCode()); //2018699554
System.out.println(clone.hashCode()); //1311053135
System.out.println(mirror.hashCode()); //2018699554
Custom "contains"
The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values.
As a workaround, you could implement your own contains method. Something like:
If you wish to get the index:
static int indexOfArray(List<String[]> list, String[] twin)
{
for (int i=0;i<list.size();i++)
if (Arrays.equals(list.get(i),twin))
return i;
return -1;
}
And then, call it like:
String[] toSearch = new String[]{"apple","ball"};
int index = indexOfArray(action, toSearch);
if (index>0)
System.out.println("Array found at index "+index);
else
System.out.println("Array not found");
If the index is bigger than -1, you can get your original array by just:
String[] myArray = action.get(index);
HashMap + identifier
An alternative would be storing the arrays into a HashMap by declaring an identifier for each array. For example:
Base64 ID
This will give the same result for the same values, as the encoded value is based on the entries, not the Object's reference.
static String getIdentifier(String[] array)
{
String all="";
for (String s : array)
all+=s;
return Base64.getEncoder().encodeToString(all.getBytes());
}
And then you could:
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"}; // *[1234]
action.add(items);
arrayMap.put(getIdentifier(items), items); // id = QUJDYWFh
//....
//Directly finding the twin will fail
String[] toSearch = new String[]{"apple","pear", "banana"}; // *[1556]
System.out.println(action.contains(toSearch)); // false
//But if we get the identifier based on the values
String arrId = getIdentifier(toSearch); // id = QUJDYWFh
System.out.println(action.contains(arrayMap.get(arrId))); //true
//arrayMap.get(arrId)-> *[1234]
//.....
Name.
Choose a representative name and use it as Id
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"};
action.add(items);
arrayMap.put("fruits", items);
//...
System.out.println(action.contains(arrayMap.get("fruits"))); // true
The 'contains' method compares equivalent hashCode values.
So if you make it like below*, it will pass.
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"appple","ball"};
action.add(items);
System.out.println("TO STRING");
System.out.println("--"+action.get(0));
System.out.println("--"+new String[]{"apple","ball"});
System.out.println("HASHCODES");
String[] sameValues = new String[]{"apple","ball"};
System.out.println("--"+action.get(0).hashCode());
System.out.println("--"+items.hashCode());
System.out.println("--"+sameValues.hashCode());
System.out.println("CONTAINS");
System.out.println("--"+action.contains(items)); // *this
System.out.println("--"+action.contains(sameValues));
System.out.println("--"+action.contains(new String[]{"apple","ball"}));
}
}
result is:
TO STRING
--[Ljava.lang.String;#7b1d7fff
--[Ljava.lang.String;#299a06ac
HASHCODES
--1243554231
--1243554231
--2548778887
CONTAINS
--true
--false
--false
Regarding the code shown when printing the array, these don't override toString(), so you get:
getClass().getName() + '#' + Integer.toHexString(hashCode())
For example:
[Ljava.lang.String;#7b1d7fff
[ stands for single dimension array
Ljava.lang.String stands for the type
#
7b1d7fff Hex representation of the hashcode
However, if you want to compare the values, there is the following method.
public class main {
public static void main(String[] args) {
String[] items = new String[]{"apple","ball"};
ArrayList<String> action = new ArrayList<>(Arrays.asList(items));
if (action.contains("apple")) {
System.out.println("Yes");
}
}
}
You can iterate over this list and for each element, i.e. array, call Arrays.equals method to check equality of arrays until first match, or till the end of the list if none match. In this case it can return true for each element:
List<String[]> list = List.of(
new String[]{"appple", "ball"},
new String[]{"appple", "ball"});
String[] act = new String[]{"appple", "ball"};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
This method internally calls String#equals method for each element of the array, i.e. String, so this code also returns true:
List<String[]> list = List.of(
new String[]{new String("appple"), new String("ball")},
new String[]{new String("appple"), new String("ball")});
String[] act = new String[]{new String("appple"), new String("ball")};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
According to JavaDocs, "contains" method is using "equals" and "hashCode" methods in order to check whether an object is contained.
A leading question:
Do you know what's the implementation of "equals" for arrays?
Check it and you will probably understand your code's execution result (hint: ==).
As "Hovercraft Full Of Eels" said, a better design will be using a list of some Collection which you DO understand / control it's "equals" and "hashCode" methods.
I have 2 Arrays.
One Array has Strings, which i look for.
static String[] namesToLookFor = { "NR", "STAFFELNR", "VONDATUM"};
the otherArray has Strings, which i got from a *.csv file.
indexString = indexReader.readLine();
indexArray = indexString.split(";");
My Goal is to system.out.println() the Values which are the indexArray[] and NOT in the namesToLookFor[].
For example:
namesToLookFor = {"NR"};
indexArray = {"HELLO","NR"};
//Any Algorithm here...
So in this case"HELLO" should be printed out, since it is NOT in the namesToLookFor[] Array.
If you are using java8 you can do the following
List<String> list = Arrays.asList(namesToLookFor);
Arrays.stream(indexArray)
.filter(item -> !list.contains(item))
.forEach(System.out::println);
You could iterate over your indexArray and check for each element if its contained in your namesToLookFor Array:
String[] namesToLookFor = {"NR"};
String[] indexArray = {"HELLO","NR"};
List<String> excludedNames = Arrays.asList(namesToLookFor);
for(String s : indexArray) {
if (!excludedNames.contains(s)) {
System.out.println(s);
}
}
Will output only "HELLO".
// Put array into set for better performance
Set<String> namesToFilter = new HashSet<>(Arrays.asList("NR", "STAFFELNR"));
String[] indexArray = indexReader.readLine().split(";");
// Create list with unfiltered values and remove unwanted ones
List<String> resultList = new ArrayList<>(indexArray);
resultList.removeAll(namesToFilter);
// Do with result whatever you want
for (String s : resultList)
System.out.println(s);
With Array you can use contains function but after converting it to be ArrayList, the contains function will check if the ArrayList contains a specific value.
for (int i =0; i<indexArray.length; i++) {
if (!Arrays.asList(namesToLookFor).contains(indexArray[i]))
System.out.println(indexArray[i]);
}
I need to parse a formula and get all the variables that were used. The list of variables is available. For example, the formula looks like this:
String f = "(Min(trees, round(Apples1+Pears1,1)==1&&universe==big)*number";
I know that possible variables are:
String[] vars = {"trees","rivers","Apples1","Pears1","Apricots2","universe","galaxy","big","number"};
I need to get the following array:
String[] varsInF = {"trees", "Apples1","Pears1", "universe", "big","number"};
I believe that split method is good here but can’t figure the regexp required for this.
No need for any regex pattern - just check which item of the supported vars is contained in the given string:
List<String> varsInf = new ArrayList<>();
for(String var : vars)
if(f.contains(var))
varsInf.add(var);
Using Stream<> you can:
String[] varsInf = Arrays.stream(vars).filter(f::contains).toArray(String[]::new);
Assuming "variable" is represented by one alphanumeric character or sequential sequence of multiple such characters, you should split by not-alphanumeric characters, i. e. [^\w]+, then collect result by iteration or filter:
Set<String> varSet = new HashSet<>(Arrays.asList(vars));
List<String> result = new ArrayList<>();
for (String s : f.split("[^\\w]+")) {
if (varSet.contains(s)) {
result.add(s);
}
}
I'm trying to generate all possible combinations of sentences. As variables I have two Strings, one String will be the subject, e.g. health and one will be an object, such as fruit, but then I will have a List<String> of values associated with one "head" word, so in keeping with the two components just mentioned, they would be associated with the list [improve, change, alter, modify]. I want to generate all possible combinations of these sentences and add each one to the List<Sentences> with something like:
Sentence example_sentence = new Sentence(verb, object, subject);
sentences.add(example_sentence);
Right now the larger function in which this is taking place looks like this:
public Sentence dataPreprocessing(String raw_subject, String raw_object, String raw_verb, List<Sentence> sentences) throws IOException {
WordNet wordnet = new WordNet();
String verb = wordnet.getStem(raw_verb);
String object = wordnet.getStem(raw_object);
String subject = wordnet.getStem(raw_subject);
List<String> verb_hypernym_container = new ArrayList<>();
verb_hypernym_container = wordnet.getHypernyms(verb, POS.VERB);
//wordnet.getHypernyms(this.object, POS.NOUN);
//wordnet.getHypernyms(this.subject, POS.NOUN);
Sentence return_sentence = new Sentence( verb, object, subject );
return return_sentence;
}
How can I most effectively achieve this goal of generating all possible sentences?
Since you have a fixed number of lists, the simplest way is to just use nested loops:
List<Sentence> sentences = new ArrayList<>();
for(String verb_hypernym : wordnet.getHypernyms(verb, POS.VERB))
for(String object_hypernym : wordnet.getHypernyms(object, POS.NOUN))
for(String subject_hypernym : wordnet.getHypernyms(subject, POS.NOUN))
sentences.add(new Sentence(verb_hypernym, object_hypernym, subject_hypernym));
return sentences;
Or, to avoid calling getHypernyms more often than necessary:
List<String> verb_hypernyms = wordnet.getHypernyms(verb, POS.VERB);
List<String> object_hypernyms = wordnet.getHypernyms(object, POS.NOUN);
List<String> subject_hypernyms = wordnet.getHypernyms(subject, POS.NOUN);
for(String verb_hypernym : verb_hypernyms)
for(String object_hypernym : object_hypernyms)
for(String subject_hypernym : subject_hypernyms)
sentences.add(new Sentence(verb_hypernym, object_hypernym, subject_hypernym));
return sentences;
Once you have a list of nouns and verbs you could use streams to return a list of sentences. This also gives you a chance to remove any duplicates, sort or anything else you need to do to the stream.
List<Sentence> sentences = subjectList.stream()
.flatMap(object -> verbList.stream()
.flatMap(verb -> objectList.stream()
.map(subject -> new Sentence(object, verb, subject))))
.distinct()
.collect(Collectors.toList());
I've array-list "mArrayListvarinats" of String which contains pipe separated strings like
225356175|225356176|225356177|225356178|225356179|225356180|225356181|225356182|225356183|225356184|225356185|225356186|225356187|225356188|225356189|225356190|225356191|225356192
The size of mArrayListvarinats may be 0 upto n Now I want to find out common string between those Strings from mArrayListvarinats.
for ex. if it's size is two the code may be like as follows.
String temp[] = mArrayListvarinats.get(0).split("\\|");
String temp1[] = mArrayListvarinats.get(1).split("\\|");
and then loop will work on both the arrays to get common one.But how to achieve it for any no of size inside the loop as those temp arrays will be generated in the loop on mArrayListvarinats?
Something like this should work :
HashSet<String> allStrings = new HashSet<String>();
HashSet<String> repeatedStrings = new HashSet<String>();
for(String pipedStrings: mArrayListvarinats){
String temp[] = pipedStrings.split("\\|");
for(String str : temp){
if(!allStrings.add(str)){
repeatedStrings.add(str);
}
}
}
This way, you will have your HashSet allStrings that contains all your unique strings. And the other HashSet repeatedStrings which contains all the strings that appears more than once.
Try this short version:
public static void main(String[] args) {
List<String> a = new ArrayList<>(asList("225356176|225356177|225356178".split("\\|")));
List<String> b = new ArrayList<>(asList("225356175|225356176|225356177".split("\\|")));
a.retainAll(b);
b.retainAll(a);
System.out.println(b);
}
OUTPUT:
[225356176, 225356177]
Iterate through each of them and put them in a HashSet. If you get false while adding it means it's already there. You can put it in a separate Hashset. this way you will get a hashset of all unique string and an another hashset of strings that occured multiple times
Set<String> set=new HashSet<String>();
for (int i = 0; i < temp.length; i++) {
set.add(str[i]);
}
for (int i = 0; i < temp1.length; i++) {
set.add(str1[i]);
}
The set will contain common strings.
If you are only interested in getting common strings found in mArrayListvarinats variable, then you should use Set data structure. Set in java will only contain unique entries. From the example strings it sounds that you are collecting string which has numeric values. So there won't be any problem due to that. But if you are collecting alpha numeric value then you need to take care of alphabet's case, as Set collects values which are case sensitive. So for Set A is not equal to a.
This will find common among all your lists.
List<String> common = Arrays.asList(mArrayListvarinats.get(0).split("\\|"));
for(String varinats: mArrayListvarinats){
List<String> items = Arrays.asList(varinats.split("\\|"));
common = ListUtils.intersection(items,common);
}
But for this you have to use Apache commons collection library , which I hope is not a issue for you :)
Below code will return you the frequency of each string present in the array.
public static void main(String[] args) {
String mArrayListvarinats = "225356175,225356176,225356177,225356178,225356179,225356180,225356181,225356182,225356183,225356184,225356185,225356186,225356187,225356188,225356189,225356190,225356191,225356192,225356192";
List<String> list = Arrays.asList(mArrayListvarinats.split(","));
Set<String> uniqueWords = new HashSet<String>(list);
for (String word : uniqueWords) {
System.out.println(word + ": " + Collections.frequency(list, word));
}
}
String with frequency more than 1 are duplicates/common. You can take actions based on frequency.