I have a String[] with values like so:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Given String s, is there a good way of testing whether VALUES contains s?
Arrays.asList(yourArray).contains(yourValue)
Warning: this doesn't work for arrays of primitives (see the comments).
Since java-8 you can now use Streams.
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
To check whether an array of int, double or long contains a value use IntStream, DoubleStream or LongStream respectively.
Example
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
Concise update for Java SE 9
Reference arrays are bad. For this case we are after a set. Since Java SE 9 we have Set.of.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Given String s, is there a good way of testing whether VALUES contains s?"
VALUES.contains(s)
O(1).
The right type, immutable, O(1) and concise. Beautiful.*
Original answer details
Just to clear the code up to start with. We have (corrected):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
This is a mutable static which FindBugs will tell you is very naughty. Do not modify statics and do not allow other code to do so also. At an absolute minimum, the field should be private:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Note, you can actually drop the new String[]; bit.)
Reference arrays are still bad and we want a set:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Paranoid people, such as myself, may feel more at ease if this was wrapped in Collections.unmodifiableSet - it could then even be made public.)
(*To be a little more on brand, the collections API is predictably still missing immutable collection types and the syntax is still far too verbose, for my tastes.)
You can use ArrayUtils.contains from Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Note that this method returns false if the passed array is null.
There are also methods available for primitive arrays of all kinds.
Example:
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Just simply implement it by hand:
public static <T> boolean contains(final T[] array, final T v) {
for (final T e : array)
if (e == v || v != null && v.equals(e))
return true;
return false;
}
Improvement:
The v != null condition is constant inside the method. It always evaluates to the same Boolean value during the method call. So if the input array is big, it is more efficient to evaluate this condition only once, and we can use a simplified/faster condition inside the for loop based on the result. The improved contains() method:
public static <T> boolean contains2(final T[] array, final T v) {
if (v == null) {
for (final T e : array)
if (e == null)
return true;
}
else {
for (final T e : array)
if (e == v || v.equals(e))
return true;
}
return false;
}
Four Different Ways to Check If an Array Contains a Value
Using List:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
Using Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
Using a simple loop:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
Using Arrays.binarySearch():
The code below is wrong, it is listed here for completeness. binarySearch() can ONLY be used on sorted arrays. You will find the result is weird below. This is the best option when array is sorted.
public static boolean binarySearch(String[] arr, String targetValue) {
return Arrays.binarySearch(arr, targetValue) >= 0;
}
Quick Example:
String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false
If the array is not sorted, you will have to iterate over everything and make a call to equals on each.
If the array is sorted, you can do a binary search, there's one in the Arrays class.
Generally speaking, if you are going to do a lot of membership checks, you may want to store everything in a Set, not in an array.
For what it's worth I ran a test comparing the 3 suggestions for speed. I generated random integers, converted them to a String and added them to an array. I then searched for the highest possible number/string, which would be a worst case scenario for the asList().contains().
When using a 10K array size the results were:
Sort & Search : 15
Binary Search : 0
asList.contains : 0
When using a 100K array the results were:
Sort & Search : 156
Binary Search : 0
asList.contains : 32
So if the array is created in sorted order the binary search is the fastest, otherwise the asList().contains would be the way to go. If you have many searches, then it may be worthwhile to sort the array so you can use the binary search. It all depends on your application.
I would think those are the results most people would expect. Here is the test code:
import java.util.*;
public class Test {
public static void main(String args[]) {
long start = 0;
int size = 100000;
String[] strings = new String[size];
Random random = new Random();
for (int i = 0; i < size; i++)
strings[i] = "" + random.nextInt(size);
start = System.currentTimeMillis();
Arrays.sort(strings);
System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
System.out.println("Sort & Search : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
System.out.println("Search : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.asList(strings).contains("" + (size - 1)));
System.out.println("Contains : "
+ (System.currentTimeMillis() - start));
}
}
Instead of using the quick array initialisation syntax too, you could just initialise it as a List straight away in a similar manner using the Arrays.asList method, e.g.:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Then you can do (like above):
STRINGS.contains("the string you want to find");
With Java 8 you can create a stream and check if any entries in the stream matches "s":
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Or as a generic method:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
You can use the Arrays class to perform a binary search for the value. If your array is not sorted, you will have to use the sort functions in the same class to sort the array, then search through it.
ObStupidAnswer (but I think there's a lesson in here somewhere):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Actually, if you use HashSet<String> as Tom Hawtin proposed you don't need to worry about sorting, and your speed is the same as with binary search on a presorted array, probably even faster.
It all depends on how your code is set up, obviously, but from where I stand, the order would be:
On an unsorted array:
HashSet
asList
sort & binary
On a sorted array:
HashSet
Binary
asList
So either way, HashSet for the win.
Developers often do:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
The above code works, but there is no need to convert a list to set first. Converting a list to a set requires extra time. It can as simple as:
Arrays.asList(arr).contains(targetValue);
or
for (String s : arr) {
if (s.equals(targetValue))
return true;
}
return false;
The first one is more readable than the second one.
If you have the google collections library, Tom's answer can be simplified a lot by using ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
This really removes a lot of clutter from the initialization proposed
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
In Java 8 use Streams.
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
One possible solution:
import java.util.Arrays;
import java.util.List;
public class ArrayContainsElement {
public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");
public static void main(String args[]) {
if (VALUES.contains("AB")) {
System.out.println("Contains");
} else {
System.out.println("Not contains");
}
}
}
Using a simple loop is the most efficient way of doing this.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Courtesy to Programcreek
the shortest solution
the array VALUES may contain duplicates
since Java 9
List.of(VALUES).contains(s);
Use the following (the contains() method is ArrayUtils.in() in this code):
ObjectUtils.java
public class ObjectUtils {
/**
* A null safe method to detect if two objects are equal.
* #param object1
* #param object2
* #return true if either both objects are null, or equal, else returns false.
*/
public static boolean equals(Object object1, Object object2) {
return object1 == null ? object2 == null : object1.equals(object2);
}
}
ArrayUtils.java
public class ArrayUtils {
/**
* Find the index of of an object is in given array,
* starting from given inclusive index.
* #param ts Array to be searched in.
* #param t Object to be searched.
* #param start The index from where the search must start.
* #return Index of the given object in the array if it is there, else -1.
*/
public static <T> int indexOf(final T[] ts, final T t, int start) {
for (int i = start; i < ts.length; ++i)
if (ObjectUtils.equals(ts[i], t))
return i;
return -1;
}
/**
* Find the index of of an object is in given array, starting from 0;
* #param ts Array to be searched in.
* #param t Object to be searched.
* #return indexOf(ts, t, 0)
*/
public static <T> int indexOf(final T[] ts, final T t) {
return indexOf(ts, t, 0);
}
/**
* Detect if the given object is in the given array.
* #param ts Array to be searched in.
* #param t Object to be searched.
* #return If indexOf(ts, t) is greater than -1.
*/
public static <T> boolean in(final T[] ts, final T t) {
return indexOf(ts, t) > -1;
}
}
As you can see in the code above, that there are other utility methods ObjectUtils.equals() and ArrayUtils.indexOf(), that were used at other places as well.
For arrays of limited length use the following (as given by camickr). This is slow for repeated checks, especially for longer arrays (linear search).
Arrays.asList(...).contains(...)
For fast performance if you repeatedly check against a larger set of elements
An array is the wrong structure. Use a TreeSet and add each element to it. It sorts elements and has a fast exist() method (binary search).
If the elements implement Comparable & you want the TreeSet sorted accordingly:
ElementClass.compareTo() method must be compatable with ElementClass.equals(): see Triads not showing up to fight? (Java Set missing an item)
TreeSet myElements = new TreeSet();
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
// *Alternatively*, if an array is forceably provided from other code:
myElements.addAll(Arrays.asList(myArray));
Otherwise, use your own Comparator:
class MyComparator implements Comparator<ElementClass> {
int compareTo(ElementClass element1; ElementClass element2) {
// Your comparison of elements
// Should be consistent with object equality
}
boolean equals(Object otherComparator) {
// Your equality of comparators
}
}
// construct TreeSet with the comparator
TreeSet myElements = new TreeSet(new MyComparator());
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
The payoff: check existence of some element:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
If you don't want it to be case sensitive
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Try this:
ArrayList<Integer> arrlist = new ArrayList<Integer>(8);
// use add() method to add elements in the list
arrlist.add(20);
arrlist.add(25);
arrlist.add(10);
arrlist.add(15);
boolean retval = arrlist.contains(10);
if (retval == true) {
System.out.println("10 is contained in the list");
}
else {
System.out.println("10 is not contained in the list");
}
Check this
String[] VALUES = new String[]{"AB", "BC", "CD", "AE"};
String s;
for (int i = 0; i < VALUES.length; i++) {
if (VALUES[i].equals(s)) {
// do your stuff
} else {
//do your stuff
}
}
Arrays.asList() -> then calling the contains() method will always work, but a search algorithm is much better since you don't need to create a lightweight list wrapper around the array, which is what Arrays.asList() does.
public boolean findString(String[] strings, String desired){
for (String str : strings){
if (desired.equals(str)) {
return true;
}
}
return false; //if we get here… there is no desired String, return false.
}
Use below -
String[] values = {"AB","BC","CD","AE"};
String s = "A";
boolean contains = Arrays.stream(values).anyMatch(v -> v.contains(s));
Use Array.BinarySearch(array,obj) for finding the given object in array or not.
Example:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false --not exists
Try using Java 8 predicate test method
Here is a full example of it.
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Test {
public static final List<String> VALUES =
Arrays.asList("AA", "AB", "BC", "CD", "AE");
public static void main(String args[]) {
Predicate<String> containsLetterA = VALUES -> VALUES.contains("AB");
for (String i : VALUES) {
System.out.println(containsLetterA.test(i));
}
}
}
http://mytechnologythought.blogspot.com/2019/10/java-8-predicate-test-method-example.html
https://github.com/VipulGulhane1/java8/blob/master/Test.java
Create a boolean initially set to false. Run a loop to check every value in the array and compare to the value you are checking against. If you ever get a match, set boolean to true and stop the looping. Then assert that the boolean is true.
As I'm dealing with low level Java using primitive types byte and byte[], the best so far I got is from bytes-java https://github.com/patrickfav/bytes-java seems a fine piece of work
You can check it by two methods
A) By converting the array into string and then check the required string by .contains method
String a = Arrays.toString(VALUES);
System.out.println(a.contains("AB"));
System.out.println(a.contains("BC"));
System.out.println(a.contains("CD"));
System.out.println(a.contains("AE"));
B) This is a more efficent method
Scanner s = new Scanner(System.in);
String u = s.next();
boolean d = true;
for (int i = 0; i < VAL.length; i++) {
if (VAL[i].equals(u) == d)
System.out.println(VAL[i] + " " + u + VAL[i].equals(u));
}
Related
I have a collection of strings in an array like this:
ArrayList<String> collection = new ArrayList<>();
That stores:
collection: ["(,0,D=1", "(,1,D=2", "),2,D=2", "),3,D=1", "(,4,D=1", "(,5,D=2", "),6,D=2", "),7,D=1"]
I have a lot of d=1 and d=2, as you can see. How do I organize this from 1 first to 2? I tried to use a for loop but the list can contain an infinite number of d=x's. Can you help me organize?
Also, please help me so I don't change the ORDER of any numbers. Example:
collection: ["(,0,D=1", "),3,D=1", "(,4,D=1", "),7,D=1", "(,1,D=2", "),2,D=2", "(,5,D=2", "),6,D=2"]
So like, every parentheses will be aligned.
I should note that collection[0] = "(,0,D=1"
You should use a class for the items, not a string, e.g. Class Item {char c; int i; int depth;} and ArrayList. Then you can easily sort the list with a custom Comparator.
You can implement your own Comparator to do the sorting. A Comparator is a sorting algorithms that you define for your application which written in programming language. Give Collections.sort() a Comparator basically you teach Java how you want to sort the list. And it will sort the list for you.
This implementation is based on the following assumptions:
The comparison will only take effect on the first D=x pattern, subsequent will be ignored.
Element is sorted in ascending order base on x.
Elements do not have D=x will be placed at the back
class DeeEqualComparator implements Comparator<String> {
private static final String REGEX = "D=([0-9])+";
#Override
public int compare(String s1, String s2) {
// find a D=x pattern from the element
Matcher s1Matcher = Pattern.compile(REGEX).matcher(s1);
Matcher s2Matcher = Pattern.compile(REGEX).matcher(s2);
boolean s1Match = s1Matcher.find();
boolean s2Match = s2Matcher.find();
if (s1Match && s2Match) {
// if match is found on s1 and s2, return their integer comparison result
Integer i1 = Integer.parseInt(s1Matcher.group(1));
Integer i2 = Integer.parseInt(s2Matcher.group(1));
return i1.compareTo(i2);
} else if (s1Match) {
// if only s1 found a match
return -1;
} else if (s2Match) {
// if only s2 found a match
return 1;
} else {
// if no match is found on both, return their string comparison result
return s1.compareTo(s2);
}
}
Test run
public static void main(String[] args) {
String[] array = {
// provided example
"(,0,D=1", "(,1,D=2", "),2,D=2", "),3,D=1", "(,4,D=1", "(,5,D=2", "),6,D=2", "),7,D=1"
// extra test case
, "exception-5", "exception-0", "D=68" };
List<String> list = Arrays.asList(array);
Collections.sort(list, new DeeEqualComparator());
System.out.print(list);
}
output
[(,0,D=1, ),3,D=1, (,4,D=1, ),7,D=1, (,1,D=2, ),2,D=2, (,5,D=2, ),6,D=2, D=68, exception-0, exception-5]
I need to write a static method in a class MinTester that computes the "smallest" string
from an ArrayList collection using a comparator object:
public static String min(ArrayList<String> list, Comparator<String> comp)
I cannot use the Collections class to compute the minimum.
Here is what I have so far.
public class MinTester
{
static String least;//This is static because it is being used in a static static context
public static String min(ArrayList<String> list, Comparator<String> comp)
{
int min = 0;
for( int i = 0; i < list.size(); i++ )
{
min = list.get(i).compareTo(list.get(i++));
if(min < 0)
{
least = list.get(i);
}
else if(min == 0)
{
least = list.get(i);
}
else
{
least = list.get(i++);
}
}
return least;
}
}
I am using the min value because I read that the compareTo method returns negative, 0, or positive whether the first string is less than, equal to, or greater than the second.
I am not getting any errors here from the method, So I try to test it in Main with this.
I get this warning: "Accessing static method min"
public static void main(String[] args)
{
// TODO code application logic here
MinTester s = new MinTester();
Comparator<String> comp = null;
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
String a = s.min(list,comp);//Warning: Accessing static method min
System.out.println(a);
}
My output from a = "abcd". Can anyone help me figure out why I am getting "abcd" as the 'Min' string in the list? I am thinking that my error is coming from my min() method, but I am not sure where inside it or why.
If you need to find the shortest String in an ArrayList without sorting it, you can simply traverse the list and check the .length attribute of every String, always keeping track of the shortest one.
String shortest = list.get(0);
for(String str : list) {
if (str.length() < shortest.length()) {
shortest = str;
}
}
System.out.println("The shortest string: " + shortest);
EDIT :
You would use Comparator if you wanted to implement custom comparison of two strings. Comparing their length can be done in 1 line, so Comparator is really not necessary. If you absolutely need to use the Comparator, you would replace
if (str.length() < shortest.length())
by
if (comp.compare(str, shortest) < 0))
it's basically the same thing, except that you don't define the comparison by yourself but leave it up to the Comparator to decide, which String of the two is smaller. This way, if you wanted the way how the strings are compared in the future, you wouldn't have to rewrite the method, you would only supply a different Comparator.
Using Streams and Comparator-
Comparator<String> comparator = (str1, str2) -> str1.length() > str2.length() ? 1 : -1;
String smallest = Arrays.stream(input)
.sorted(comparator).findFirst().get();
Reference: Find Shortest Length String
you can just use string lengths to compare and use min method of stream:
stringSet.stream().min(Comparator.comparingInt(String::length)).get();
Some pointer, using the Comparator, to get the idea. I'm not going to solve the whole problem, as this is obviously your homework (implement the Comparator for the String lengths, understand what Comparator#compareTo(T, T) returns, read the Comparator API):
public static String min(List<String> list, Comparator<String> comp) {
String shortest = null;
for (String current : list) {
if (shortest == null) { // first iteration
shortest = current;
continue;
}
int comparisonResult = comp.compare(shortest, current);
// TODO: your task; update shortest, depending on comparisonResult
}
return shortest;
}
Don't want to do all of the work for you, so I will provide a solution in Scala:
object MinTest{
def main(args: Array[String]){
val list: util.List[String] = List("a", "ab", "abc", "abcd")
val m: String = min(list, (s1, s2) => s1.length - s2.length)
println(m) //output is: a
}
def min(list: util.List[String], comp: (String, String) => Int): String = {
if(list.isEmpty)
return null
var min = list(0)
for(i <- 0 until list.size if comp(list(i), min) < 0)
min = list(i)
min
}
}
Although this is a different language, the logic is still present. It's just your responsibility to convert it to Java.
This is simple guys, cant you just create a hashmap from a list where the number in the hashmap is the length of the string then the value in the hashmap is the string that goes with that value...
Sort by the key, select item zero, then you have it , right?
What I'm saying is put all the strings in a list.. for each loop on that list, while doing so note the string in one column and the length of that string in the other "while you're there" , sort by the length, then pick the first string that goes with that length.
You can get the length of the string element using the length method
e.g. list.get(0).length()
This should return the size of the string
Good Luck
I have an arraylist of Strings that want to have all possible combinations stored into another collection.
For example:
[air,bus,car]
->
[air]
[bus]
[car]
[air,bus]
[air,car]
[bus,air]
[bus,car]
[car,air]
[car,bus]
[air,bus,car]
[air,car,bus]
...
[car,bus,air]
Repetitions are not important. The code right now I have is:
public ArrayList<String> comb(ArrayList<String> wrds, ArrayList<String> str, int size)
{
ArrayList<String> s = new ArrayList<String>();
s.addAll(str);
if(size != a1.size())
{
Iterator e = a1.iterator();
while(e.hasNext())
{
s.add((String)e.next());
}
size++;
}
}
I am trying to get it to recursively call itself so it can store the combinations. Can I get any help as to where or which part I am missing in my code?
Seeing as this is homework, I'll try to give you background to the answer.
The key to solving this is to use recursion.
First imagine you have two items in your array. You'd could remove the first item to give you your first combination. Adding the remaining item to the first item gives you the second combination. Removing the second item give you the third combination. Adding the remaining item gives you the forth combination. If you had ["air", "bus"] it'd be something like:
["air"]
["air", "bus"]
["bus"]
["bus", "air"]
A method that returns that might look like:
String[][] combinations(String[] strings)
The important things to note are the an array containing a single string can be passed to this method and it can return an array containing an array with a single string in it.
The problem is complicated a little because you have to keep a tally of the string combinations, so before we get to solving that, it's important that you understand recursion.
Imagine you wanted to write a multiplication method that takes two numbers and multiplies them but you only have addition and subtraction at your disposal. You could write a recursive function that adds one of the numbers to itself until the other number reaches an exit condition, something like:
public int multiply(int value1, int value2)
{
if (value1 > 1)
{
int remaining = value1 - 1;
return value2 + multiply(remaining, value2);
}
else
{
return value2;
}
}
You can do just the same thing with an array, only instead to exiting when the a value hit's 1 you exit when the array contains one item, something like:
public String[][] combinations(String[] strings)
{
if (strings.length > 1)
{
...
}
else
{
return new String[][]{strings};
}
}
For reasons with the Java API it's much easier to use java.util.List rather than arrays so you want something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size()> 1)
{
...
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(strings);
return result;
}
}
Now it's the ... that's the important bit. You need to keep an list-of-lists that will be the result and iterate over the strings. For each of the strings you can add that string to the results and then you need create a sub-list that is minus the current string, which you use to call the combinations method again iterating over the result adding the current string each list it contains. In code it looks something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size() > 1)
{
List<List<String>> result = new ArrayList<List<String>>();
for (String str : strings)
{
List<String> subStrings = new ArrayList<String>(strings);
subStrings.remove(str);
result.add(new ArrayList<String>(Arrays.asList(str)));
for (List<String> combinations : combinations(subStrings))
{
combinations.add(str);
result.add(combinations);
}
}
return result;
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(new ArrayList<String>(strings));
return result;
}
}
In summary, what you're doing is reducing the list of strings down to a single item, then combining it with the preceeding items to produce all the possible combinations as the thread returns up the call stack.
public static void combination(Object[] array){
for(int x = 0; x < (1 << array.length); x++){
System.out.print("[");
for(int y = 0; y < array.length; y++){
if(checkIsOn(x, y){
System.out.print(array[y]);
}
}
System.out.println("]");
}
}
public static boolean checkIsOn(int mast, int position){
return (mast & (1 << position) > 0);
}
Use the list as a parameter to the recursive function. You can call the function from within itself with a new list containing everything except the first item.
I am trying to write a quick search that searches a List<String>
Instead of looping through the list and manually checking, I want to do this using binarySearch, but I am not sure how to do it.
Old way:
for(String s : list) {
if(s.startsWith("contact.")
return true;
}
Instead I would like something like this:
Collections.sort(list);
Collections.binarySearch(list, FindContactComparator());
Can someone help me write this Comparator?
Is there any better way of doing this instead of using binarySearch?
This should work:
Comparator<String> startsWithComparator = new Comparator<String>() {
public int compare(String currentItem, String key) {
if(currentItem.startsWith(key)) {
return 0;
}
return currentItem.compareTo(key);
}
};
int index = Collections.binarySearch(items, "contact.", startsWithComparator);
However sorting and then binary searching is less efficient than the single pass iteration.
Addendum:
Though the above answer helps you, here is another way (inspired from Scala, Google Collections) :
List<String> items = Arrays.asList("one", "two", "three", "four", "five", "six");
int index = find(items, startsWithPredicate("th"));
System.out.println(index);
public static Predicate<String> startsWithPredicate(final String key) {
return new Predicate<String>(){
#Override
public boolean apply(String item) {
return item.startsWith(key);
}
};
}
public static <T> int find(Collection<T> items, Predicate<T> predicate) {
int index = 0;
for(T item: items) {
if(predicate.apply(item)) {
return index;
}
index++;
}
return -1;
}
interface Predicate<T> {
boolean apply(T item);
}
Here the thing is the find() method is not tied with your 'matching' logic; it just finds an element that satisfies the predicate. So you could pass on a different implementation of predicate, for ex. which can check 'endsWith' to find() method and it would return the found item which ends with a particular string. Further the find() method works for any type of collection; all it needs is a predicate which transforms an element of collection element type to a boolean. This multiple lines of code around a simple logic also show the Java's lack of support for first class functions.
The problem is that binary search never looks back.
I solved this by finding the first matching an element using binary search, then loop backward to find the first occurrence of this substring, followed by a loop which collects all matching elements.
I think that the way you are doing this now is actually the best way from a performance standpoint. Sorting itself is probably more expensive than simply iterating through the unsorted list. But to be sure you would have to run some tests (although that's not as easy as it may sound due to JIT compilation).
Is the criterium you are looking for always 'starts with'? Because in your question you're talking about a regex.
If you do want to implement this, you should at least use the same Comparator for sorting as for searching. The comparator itself can be very simple. Just write one that puts everything that matches your criterium in front of everything that doesn't. My syntax may not be completely correct since I haven't done Java in a while.
public class MyComparator<string> implements Comparator<string> {
private string prefix;
public MyComparator(string prefix) {
this.prefix = prefix;
}
public int compare(string s0, string s1) {
if (s0.startsWith(prefix) && s1.startsWith(prefix)) {
return 0;
}
else if (s0.startsWith(prefix)) {
return -1;
}
else if (s1.startsWith(prefix)) {
return 1;
}
return 0;
}
public bool equals(object comp) {
return true;
}
}
Sorting the list itself takes more time than a linear scan of the list. (Comparison based sort takes time proportional to n(log n) where n is the length of the list.)
Even if the list is completely sorted most of the times, the sorting algorithm will have to at least iterate through the list to check this.
Basically, no matter how you implement a sorting algorithm, the algorithm (even in the best case) has to at least look at all elements. Thus, a linear search for "concat" is probably your best option here.
A more elaborate solution would be to subclass the list that contains the strings, and maintain the index of the first occurnece of "concat".
Given that strings are immutable, all you have to do is to override add, remove and so on, and update the index accordingly.
Just another comparator (with regex):
Comparator<String> comparator = new Comparator<String>() {
private final Pattern containsPattern = Pattern.compile(searchTerm,Pattern.CASE_INSENSITIVE);
public int compare(String o1, String o2) {
Matcher contains1 = containsPattern.matcher(o1);
Matcher contains2 = containsPattern.matcher(o2);
boolean find1 = contains1.find();
boolean find2 = contains2.find();
if(find1 && find2){
int compareContains = contains1.end() - contains2.end();
if (compareContains == 0) {
return o1.compareTo(o2);
} else {
return compareContains;
}
}else if(find1){
return -1;
}else if(find2){
return 1;
}else{
return o1.compareTo(o2);
}
}
};
Input ArrayList (search term: dog):
"yxcv",
"dogb",
"doga",
"abcd",
"a Dog"
Output(sorted) ArrayList:
"doga",
"dogb",
"a Dog",
"abcd",
"yxcv"
I have a String[] with values like so:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Given String s, is there a good way of testing whether VALUES contains s?
Arrays.asList(yourArray).contains(yourValue)
Warning: this doesn't work for arrays of primitives (see the comments).
Since java-8 you can now use Streams.
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
To check whether an array of int, double or long contains a value use IntStream, DoubleStream or LongStream respectively.
Example
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
Concise update for Java SE 9
Reference arrays are bad. For this case we are after a set. Since Java SE 9 we have Set.of.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Given String s, is there a good way of testing whether VALUES contains s?"
VALUES.contains(s)
O(1).
The right type, immutable, O(1) and concise. Beautiful.*
Original answer details
Just to clear the code up to start with. We have (corrected):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
This is a mutable static which FindBugs will tell you is very naughty. Do not modify statics and do not allow other code to do so also. At an absolute minimum, the field should be private:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Note, you can actually drop the new String[]; bit.)
Reference arrays are still bad and we want a set:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Paranoid people, such as myself, may feel more at ease if this was wrapped in Collections.unmodifiableSet - it could then even be made public.)
(*To be a little more on brand, the collections API is predictably still missing immutable collection types and the syntax is still far too verbose, for my tastes.)
You can use ArrayUtils.contains from Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Note that this method returns false if the passed array is null.
There are also methods available for primitive arrays of all kinds.
Example:
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Just simply implement it by hand:
public static <T> boolean contains(final T[] array, final T v) {
for (final T e : array)
if (e == v || v != null && v.equals(e))
return true;
return false;
}
Improvement:
The v != null condition is constant inside the method. It always evaluates to the same Boolean value during the method call. So if the input array is big, it is more efficient to evaluate this condition only once, and we can use a simplified/faster condition inside the for loop based on the result. The improved contains() method:
public static <T> boolean contains2(final T[] array, final T v) {
if (v == null) {
for (final T e : array)
if (e == null)
return true;
}
else {
for (final T e : array)
if (e == v || v.equals(e))
return true;
}
return false;
}
Four Different Ways to Check If an Array Contains a Value
Using List:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
Using Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
Using a simple loop:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
Using Arrays.binarySearch():
The code below is wrong, it is listed here for completeness. binarySearch() can ONLY be used on sorted arrays. You will find the result is weird below. This is the best option when array is sorted.
public static boolean binarySearch(String[] arr, String targetValue) {
return Arrays.binarySearch(arr, targetValue) >= 0;
}
Quick Example:
String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false
If the array is not sorted, you will have to iterate over everything and make a call to equals on each.
If the array is sorted, you can do a binary search, there's one in the Arrays class.
Generally speaking, if you are going to do a lot of membership checks, you may want to store everything in a Set, not in an array.
For what it's worth I ran a test comparing the 3 suggestions for speed. I generated random integers, converted them to a String and added them to an array. I then searched for the highest possible number/string, which would be a worst case scenario for the asList().contains().
When using a 10K array size the results were:
Sort & Search : 15
Binary Search : 0
asList.contains : 0
When using a 100K array the results were:
Sort & Search : 156
Binary Search : 0
asList.contains : 32
So if the array is created in sorted order the binary search is the fastest, otherwise the asList().contains would be the way to go. If you have many searches, then it may be worthwhile to sort the array so you can use the binary search. It all depends on your application.
I would think those are the results most people would expect. Here is the test code:
import java.util.*;
public class Test {
public static void main(String args[]) {
long start = 0;
int size = 100000;
String[] strings = new String[size];
Random random = new Random();
for (int i = 0; i < size; i++)
strings[i] = "" + random.nextInt(size);
start = System.currentTimeMillis();
Arrays.sort(strings);
System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
System.out.println("Sort & Search : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
System.out.println("Search : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.asList(strings).contains("" + (size - 1)));
System.out.println("Contains : "
+ (System.currentTimeMillis() - start));
}
}
Instead of using the quick array initialisation syntax too, you could just initialise it as a List straight away in a similar manner using the Arrays.asList method, e.g.:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Then you can do (like above):
STRINGS.contains("the string you want to find");
With Java 8 you can create a stream and check if any entries in the stream matches "s":
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Or as a generic method:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
You can use the Arrays class to perform a binary search for the value. If your array is not sorted, you will have to use the sort functions in the same class to sort the array, then search through it.
ObStupidAnswer (but I think there's a lesson in here somewhere):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Actually, if you use HashSet<String> as Tom Hawtin proposed you don't need to worry about sorting, and your speed is the same as with binary search on a presorted array, probably even faster.
It all depends on how your code is set up, obviously, but from where I stand, the order would be:
On an unsorted array:
HashSet
asList
sort & binary
On a sorted array:
HashSet
Binary
asList
So either way, HashSet for the win.
Developers often do:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
The above code works, but there is no need to convert a list to set first. Converting a list to a set requires extra time. It can as simple as:
Arrays.asList(arr).contains(targetValue);
or
for (String s : arr) {
if (s.equals(targetValue))
return true;
}
return false;
The first one is more readable than the second one.
If you have the google collections library, Tom's answer can be simplified a lot by using ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
This really removes a lot of clutter from the initialization proposed
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
In Java 8 use Streams.
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
One possible solution:
import java.util.Arrays;
import java.util.List;
public class ArrayContainsElement {
public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");
public static void main(String args[]) {
if (VALUES.contains("AB")) {
System.out.println("Contains");
} else {
System.out.println("Not contains");
}
}
}
Using a simple loop is the most efficient way of doing this.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Courtesy to Programcreek
the shortest solution
the array VALUES may contain duplicates
since Java 9
List.of(VALUES).contains(s);
Use the following (the contains() method is ArrayUtils.in() in this code):
ObjectUtils.java
public class ObjectUtils {
/**
* A null safe method to detect if two objects are equal.
* #param object1
* #param object2
* #return true if either both objects are null, or equal, else returns false.
*/
public static boolean equals(Object object1, Object object2) {
return object1 == null ? object2 == null : object1.equals(object2);
}
}
ArrayUtils.java
public class ArrayUtils {
/**
* Find the index of of an object is in given array,
* starting from given inclusive index.
* #param ts Array to be searched in.
* #param t Object to be searched.
* #param start The index from where the search must start.
* #return Index of the given object in the array if it is there, else -1.
*/
public static <T> int indexOf(final T[] ts, final T t, int start) {
for (int i = start; i < ts.length; ++i)
if (ObjectUtils.equals(ts[i], t))
return i;
return -1;
}
/**
* Find the index of of an object is in given array, starting from 0;
* #param ts Array to be searched in.
* #param t Object to be searched.
* #return indexOf(ts, t, 0)
*/
public static <T> int indexOf(final T[] ts, final T t) {
return indexOf(ts, t, 0);
}
/**
* Detect if the given object is in the given array.
* #param ts Array to be searched in.
* #param t Object to be searched.
* #return If indexOf(ts, t) is greater than -1.
*/
public static <T> boolean in(final T[] ts, final T t) {
return indexOf(ts, t) > -1;
}
}
As you can see in the code above, that there are other utility methods ObjectUtils.equals() and ArrayUtils.indexOf(), that were used at other places as well.
For arrays of limited length use the following (as given by camickr). This is slow for repeated checks, especially for longer arrays (linear search).
Arrays.asList(...).contains(...)
For fast performance if you repeatedly check against a larger set of elements
An array is the wrong structure. Use a TreeSet and add each element to it. It sorts elements and has a fast exist() method (binary search).
If the elements implement Comparable & you want the TreeSet sorted accordingly:
ElementClass.compareTo() method must be compatable with ElementClass.equals(): see Triads not showing up to fight? (Java Set missing an item)
TreeSet myElements = new TreeSet();
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
// *Alternatively*, if an array is forceably provided from other code:
myElements.addAll(Arrays.asList(myArray));
Otherwise, use your own Comparator:
class MyComparator implements Comparator<ElementClass> {
int compareTo(ElementClass element1; ElementClass element2) {
// Your comparison of elements
// Should be consistent with object equality
}
boolean equals(Object otherComparator) {
// Your equality of comparators
}
}
// construct TreeSet with the comparator
TreeSet myElements = new TreeSet(new MyComparator());
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
The payoff: check existence of some element:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
If you don't want it to be case sensitive
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Try this:
ArrayList<Integer> arrlist = new ArrayList<Integer>(8);
// use add() method to add elements in the list
arrlist.add(20);
arrlist.add(25);
arrlist.add(10);
arrlist.add(15);
boolean retval = arrlist.contains(10);
if (retval == true) {
System.out.println("10 is contained in the list");
}
else {
System.out.println("10 is not contained in the list");
}
Check this
String[] VALUES = new String[]{"AB", "BC", "CD", "AE"};
String s;
for (int i = 0; i < VALUES.length; i++) {
if (VALUES[i].equals(s)) {
// do your stuff
} else {
//do your stuff
}
}
Arrays.asList() -> then calling the contains() method will always work, but a search algorithm is much better since you don't need to create a lightweight list wrapper around the array, which is what Arrays.asList() does.
public boolean findString(String[] strings, String desired){
for (String str : strings){
if (desired.equals(str)) {
return true;
}
}
return false; //if we get here… there is no desired String, return false.
}
Use below -
String[] values = {"AB","BC","CD","AE"};
String s = "A";
boolean contains = Arrays.stream(values).anyMatch(v -> v.contains(s));
Use Array.BinarySearch(array,obj) for finding the given object in array or not.
Example:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false --not exists
Try using Java 8 predicate test method
Here is a full example of it.
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Test {
public static final List<String> VALUES =
Arrays.asList("AA", "AB", "BC", "CD", "AE");
public static void main(String args[]) {
Predicate<String> containsLetterA = VALUES -> VALUES.contains("AB");
for (String i : VALUES) {
System.out.println(containsLetterA.test(i));
}
}
}
http://mytechnologythought.blogspot.com/2019/10/java-8-predicate-test-method-example.html
https://github.com/VipulGulhane1/java8/blob/master/Test.java
Create a boolean initially set to false. Run a loop to check every value in the array and compare to the value you are checking against. If you ever get a match, set boolean to true and stop the looping. Then assert that the boolean is true.
As I'm dealing with low level Java using primitive types byte and byte[], the best so far I got is from bytes-java https://github.com/patrickfav/bytes-java seems a fine piece of work
You can check it by two methods
A) By converting the array into string and then check the required string by .contains method
String a = Arrays.toString(VALUES);
System.out.println(a.contains("AB"));
System.out.println(a.contains("BC"));
System.out.println(a.contains("CD"));
System.out.println(a.contains("AE"));
B) This is a more efficent method
Scanner s = new Scanner(System.in);
String u = s.next();
boolean d = true;
for (int i = 0; i < VAL.length; i++) {
if (VAL[i].equals(u) == d)
System.out.println(VAL[i] + " " + u + VAL[i].equals(u));
}