String Arraylist get the item starting with this string - java

I have a array list in which I bind the data
This is a example
MyStrings =new ArrayList<String>();
MyStrings.add("Dog");
MyStrings.add("Cat");
MyStrings.add("Can");
MyStrings.add("Ant");
MyStrings.add("Str");
Now I have a string String sweet="c";
Now what OI want is to filter that Arraylist based on my string(sweet)
so the items of the MyStrings will be only Cat and Can
EDIT
I am really sorry for the trouble I got you but my main problem is that sweet is a editable
Ive tried using this code
public void onTextChanged(CharSequence s, int start, int before,int count) {
//adapter2.getFilter().filter(s);
//int length = filterEditText.getText().length();
filterME = filterEditText.getText();
List<String> MySortStrings =new ArrayList<String>();
for(int i=0;i<MyStrings.size();i++)
{
String newString = MyStrings.get(i);
if (newString.startsWith(filterME)){
}
}
//adapter2 = new LazyAdapterGetFriends(MyFriends.this,x);
//list.setAdapter(adapter2);
}
using this declaration
LazyAdapterGetFriends adapter2;
ArrayList<String> MyStrings;
//List<String> MyStrings;
EditText filterEditText;
Sorry for my wrong question..
Foolish me

List<String> MyStrings =new ArrayList<String>();
List<String> MySortStrings =new ArrayList<String>();
MyStrings.add("Dog");
MyStrings.add("Cat");
MyStrings.add("Can");
MyStrings.add("Ant");
MyStrings.add("Str");
String sweet="c";
for(int i=0;i<MyStrings.size();i++)
{
if(MyStrings.get(i).startsWith(sweet.toUpperCase()))
{
MySortStrings.add(MyStrings.get(i));
}
}
System.out.println(MySortStrings.size());
The list MySortStrings contains the Cat & Can

These days you can also use streams to do it easily:
stringList.stream().filter(s -> s.contains("c")).collect(Collectors.toList())
When you would only need to know if there is a string in the list containing your letter (not part of the question but very useful) you can do this:
stringList.stream().anyMatch(s -> s.contains("c"))

Use str.startsWith(String, int index)
Index will tell you from which index in the str it should start comparing

The naive algorithm will be that you just filter everything out like this:
ArrayList<String> filtered = new ArrayList<String>();
for(String s : MyStrings){
if(s.substring(0,1).toLowerCase().equals("c")){
filtered.add(s);
}
}
but then you have access time in O(n).
if you need a more faster way you probably need to use a Key,Value Structure with Key set to the String you need to filter. Or even a http://en.wikipedia.org/wiki/Trie, where you can easily filter on every character in the string. But then you will need extra time in building up this thing.
Okay, this should be it when using your TextWatcher Stuff (untested...)
private List<String> MySortStrings = new ArrayList<String>(); // assume that your data is in here!
private List<String> MySortedStrings = new ArrayList<String>(); // this will be the list where your sorted strings are in. maybe you could also remove all strings which does not match, but that really depends on your situation!
public void onTextChanged(CharSequence s, int start, int before,int count) {
for(String str : MySortStrings){
if(str.startsWith(s.toString()){
MySortedStrings.add(str);
}
}
}

If you want to remove items that don't match from MyStrings rather than create a new ArrayList you will need to use an Iterator as this is the only safe way to modify a ArrayList while iterating over it.
myStrings = new ArrayList<String>();
myStrings.add("Dog");
myStrings.add("Cat");
myStrings.add("Can");
myStrings.add("Ant");
myStrings.add("Str");
String sweet="c";
sweet = sweet.toLowerCase();
Iterator<String> i = myStrings.iterator();
while (i.hasNext()) {
if (! i.next().toLowerCase().startsWith(sweet)) {
i.remove();
}
}

You can use the apache commons-collections library as well:
CollectionUtils.filter(myStrings,
new Predicate() {
public boolean evaluate(Object o) {
return ! ((String)o).startsWith("c");
}
}
};
Any object for which the "evaluate" method of the Predicate class returns false is removed from the collection. Keep in mind, that like the solution above using the Iterator, this is destructive to the list it is given. If that is an issue, you can always copy the list first:
List<String> filtered = new ArrayList<String>(myStrings);
CollectionUtils.filter(filtered, ...);

Related

Remove duplicates from a list in an Arraylist in java

I checked many examples but i could not applied for my variables.
I have a ArratyList Of lists of Strings.
ArrayList<List<String>> bulkUploadList = new ArrayList<List<String>>();
and it's look like this:
[id, title, tags, descriptions]
[4291483113.0000000000000, Camden, camdentown;london, NoValue]
[4292220054.0000000000000, IMG_2720, NoValue, NoValue]
[4292223824.0000000000000, IMG_2917, london;camdentown, NoValue]
[4292224728.0000000000000, IMG_2945, London;CamdenTown, NoValue]
I want to remove those rows which have the same titles and the same tags.
I do not know how work with HashSet since I have a ArrayList of List of Strings.
Not best solution, but you can start with this:
ArrayList<List<String>> bulkUploadList = new ArrayList<List<String>>();
ArrayList<List<String>> result = new ArrayList<List<String>>();
HashSet<String> hashSet = new HashSet<>();
for(List<String> item : bulkUploadList) {
String title = item.get(1);
String tags = item.get(2);
String uniqueString = (title + "#" + tags).trim().toUpperCase();
if(!hashSet.contains(uniqueString)) {
result.add(item);
hashSet.add(uniqueString);
} else {
System.out.println("Filtered element " + uniqueString);
}
}
As suggested in one of the comments, you should create a class for the data, make that class implement equals(), and then use HashSet to remove dups. Like this.
class Foo {
String id;
String title;
String tags;
String description;
public boolean equals(Foo this, Foo other) {
return this.id.equals(other.id)
&& this.title.equals(other.title)
&& etc.
}
then you can remove dups with
Set<Foo> set = new LinkedHashSet<Foo>(list);
as Sets do not allow duplication, and the equals() method is used to check.
You should use a linkedHashSet here because you want to preserve the order (according to a comment you made on elsewhere).
You should also implement a hashcode() method consistent with equals().

Trying to write a recursive function in Java

I am trying a lot but not able to write a recursive function for this.
For Example I have the below list of list which keeps the mapping (not a map as keys are duplicate):
[[review1, exclusivegateway4],
[exclusivegateway4, inclusivegateway1],
[inclusivegateway1, T_Review],
[inclusivegateway1, L_Review],
[inclusivegateway1, SP_Review],
[inclusivegateway1, M_Review]]
The need is to bypass the mappings which contain string 'gateway'. So as we can see that review1 is mapped to exclusivegateway4 and exclusivegateway4 is mapped to inclusivegateway1 and then inclusivegateway1 is mapped to T_Review, L_Review, SP_Review and M_Review. So bypassing all the 'gateway' string the final mapping should be:
[[review1, T_Review],
review1, L_Review],
review1, SP_Review],
review1, M_Review]]
I need to make this function recursive as there could be more gateways in there. I know that is too much to ask. But I am missing something in the code.
Thanks,
Nitin
Below is the code without recursion
private void decorateList(ArrayList<ArrayList<String>> mappingList ){
for(ArrayList<String> list: mappingList){
String src = list.get(0);
String target = list.get(1);
if(target.contains("gateway")){
listToRemove.add(list);
for(ArrayList<String> list2: mappingList){
String list2Src = list2.get(0);
String list2Target = list2.get(1);
if(list2Src.equals(target)){
if(list2Target.contains("gateway")){
for(ArrayList<String> list4: mappingList){
String list4Src = list4.get(0);
String list4Target = list4.get(1);
if(list4Src.equals(list2Target)){
ArrayList<String> list5 = new ArrayList<String>();
list5.add(src);
list5.add(list4Target);
listToAdd.add(list5);
}
}
break;
}
ArrayList<String> list3 = new ArrayList<String>();
list3.add(src);
list3.add(list2Target);
listToRemove.add(list2);
listToAdd.add(list3);
}
}
}
}
Iterator<ArrayList<String>> itr = mappingList.iterator();
while (itr.hasNext()){
ArrayList<String> list = itr.next();
if (listToRemove.contains(list)){
itr.remove();
}
}
mappingList.addAll(listToAdd);
}
And below is the code which I have written with recursion
ArrayList<ArrayList<String>> mappingList2 = mappingList;
for(ArrayList<String> list : mappingList2){
// Below line is calling the recursive function
mappingList = decorateListRecursive(mappingList, list);
}
private ArrayList<ArrayList<String>> decorateListRecursive(ArrayList<ArrayList<String>> mappingList, ArrayList<String> list){
System.out.println("Count " + count);
count++;
String src = list.get(0);
String target = list.get(1);
if(target.contains("gateway")){
listToRemove.add(list);
Iterator<ArrayList<String>> itr = mappingList.iterator();
while(itr.hasNext()){
ArrayList<String> list2 = itr.next();
String list2Src = list2.get(0);
String list2Target = list2.get(1);
if(list2Src.equals(target)){
if(list2Target.contains("gateway")){
decorateListRecursive(mappingList, list2);
}
ArrayList<String> list3 = new ArrayList<String>();
list3.add(src);
list3.add(list2Target);
listToAdd.add(list3);
}else{
}
}
}
return mappingList;
}
Uh, the recursion (as I understand the task is:)
create empty result list
call getTerminalSymbolFor(firstkey, firstkey, resultlist)
getTerminalSymbolFor(String root, String key, resultlist)
search in ArrayList for key into value
if not found: add root=key to resultlist and return
else: return getTerminalSymbolFor(root, value, resultlist) (do recursion)
From your description I am not sure if you start with any symbol, the first or non-terminal ones. But all can be adjusted. I think you might want to pass in a "resolved list" and instead of returning the found one you add it to the lis
BTW: this is horrible inefficient.
eckes algorithm helped me to get to the solution. I looped through the list and called the list recursively until I found the required Item. Then added that item into resultList.
Thanks

split an array list into multiple lists in java

I have an array list which when populated has a key and a value I want to know if there is a way of splitting it on repeating keys for example my current data is like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom, RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave, RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
I want it to come out more like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom]
[RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave]
[RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
Is there a way to split it on say role id or am I going about this the wrong way?
You can try by using HashMap
private static class MyItemHashMap extends HashMap {
public Item add(Item item) {
get(item).add(item);
return item;
}
public List get(Item key) {
List list = (List) get(createItemKey((Item) key));
return list == null ? createItemEntry((Item) key) : list;
}
private List createItemEntry(Item item) {
List list = new ArrayList();
put(createItemKey(item), list);
return list;
}
private Object createItemKey(Item item) {
return item.getSplitterProperty();
}
}
public static void main(String[] args) {
MyItemHashMap itemMapped = new MyItemHashMap();
List items = Arrays.asList(new Object[]{new Item("A"), new Item("B"),
new Item("C")});
for (Iterator iter = items.iterator(); iter.hasNext();) {
Item item = (Item) iter.next();
itemMapped.add(item);
}
}
If it is an ArrayList, there is no built-in function to split data like this; you will have to do it manually. If you know the number of consecutive fields that make a single structure, this shouldn't be too hard; something like this:
// 6 because there are 6 fields
for (int i = 0; i < arrayList.size(); i = i + 6) {
List thisList = arrayList.subList(i, i + 5);
// ... Now do whatever you want with thisList - it contains one structure.
}
If the number of fields can change then you'll have to do something a little more dynamic and loop through looking for a RoleID field, for example.
I'd use a HashMap to seperate the data instead of one long ArrayList ( you shouldn't have stored the data like this in the first instance )
HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>;
// For each list:
ArrayList<String> arr = new ArrayList<String>;
arr.add("each element");
hm.put("RoleID_123.0", arr);
This way you will end up with a three dimensional structure with a key ( "RoleID..." ) pointing to its child elements.
Try this
String[] str=new String[]{"RoleID_123.0", "UserHandel_tom", "Password_12345.0", "prevPassword_null", "userCaption_thomas", "Email_tom#tom.tom", "RoleID_124.0", "UserHandel_dave", "Password_ghadf", "prevPassword_sdfsd", "userCaption_david", "Email_dave#dave.dave", "RoleID_125.0", "UserHandel_trevor", "Password_tre", "prevPassword_null", "userCaption_trev", "Email_trev#trev.trev"};
List<String> list=new ArrayList<>(Arrays.asList(str));
List<String> subList=list.subList(0,5);
You can try something similar to this
If you feel like taking a Linq-ee Libraried approach, this is about as good as it gets, and it requires use of a couple delegate objects:
import static com.google.common.collect.Collections2.filter;
import static com.google.common.collect.Collections2.transform;
//...
final List<String> yourList = //...
final int RECORD_LENGTH = 6;
Collection<String> roleIdValues = filter(yourList, new Predicate<String>() {
public boolean apply(#Nullable String input) {
return input != null && input.startsWith("RoleID");
}
});
Collection<Collection<String>> splitRecords = transform(roleIdValues, new Function<String, Collection<String>>() {
#Nullable public Collection<String> apply(#Nullable String input) {
return yourList.subList(yourList.indexOf(input), RECORD_LENGTH);
}
});
If Oracle had delivered Java 8 on time you would be able to do this in a way more slick manor. Ironically the reason you cant was provided by the same people providing the guava library

How to convert a String into an ArrayList?

In my String, I can have an arbitrary number of words which are comma separated. I wanted each word added into an ArrayList. E.g.:
String s = "a,b,c,d,e,.........";
Try something like
List<String> myList = new ArrayList<String>(Arrays.asList(s.split(",")));
Arrays.asList documentation
String.split documentation
ArrayList(Collection) constructor documentation
Demo:
String s = "lorem,ipsum,dolor,sit,amet";
List<String> myList = new ArrayList<String>(Arrays.asList(s.split(",")));
System.out.println(myList); // prints [lorem, ipsum, dolor, sit, amet]
This post has been rewritten as an article here.
String s1="[a,b,c,d]";
String replace = s1.replace("[","");
System.out.println(replace);
String replace1 = replace.replace("]","");
System.out.println(replace1);
List<String> myList = new ArrayList<String>(Arrays.asList(replace1.split(",")));
System.out.println(myList.toString());
In Java 9, using List#of, which is an Immutable List Static Factory Methods, become more simpler.
String s = "a,b,c,d,e,.........";
List<String> lst = List.of(s.split(","));
Option1:
List<String> list = Arrays.asList("hello");
Option2:
List<String> list = new ArrayList<String>(Arrays.asList("hello"));
In my opinion, Option1 is better because
we can reduce the number of ArrayList objects being created from 2 to 1. asList method creates and returns an ArrayList Object.
its performance is much better (but it returns a fixed-size list).
Please refer to the documentation here
Easier to understand is like this:
String s = "a,b,c,d,e";
String[] sArr = s.split(",");
List<String> sList = Arrays.asList(sArr);
Ok i'm going to extend on the answers here since a lot of the people who come here want to split the string by a whitespace. This is how it's done:
List<String> List = new ArrayList<String>(Arrays.asList(s.split("\\s+")));
If you are importing or you have an array (of type string) in your code and you have to convert it into arraylist (offcourse string) then use of collections is better. like this:
String array1[] = getIntent().getExtras().getStringArray("key1"); or String array1[] = ... then
List allEds = new ArrayList(); Collections.addAll(allEds, array1);
You could use:
List<String> tokens = Arrays.stream(s.split("\\s+")).collect(Collectors.toList());
You should ask yourself if you really need the ArrayList in the first place. Very often, you're going to filter the list based on additional criteria, for which a Stream is perfect. You may want a set; you may want to filter them by means of another regular expression, etc. Java 8 provides this very useful extension, by the way, which will work on any CharSequence: https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#splitAsStream-java.lang.CharSequence-. Since you don't need the array at all, avoid creating it thus:
// This will presumably be a static final field somewhere.
Pattern splitter = Pattern.compile("\\s+");
// ...
String untokenized = reader.readLine();
Stream<String> tokens = splitter.splitAsStream(untokenized);
If you want to convert a string into a ArrayList try this:
public ArrayList<Character> convertStringToArraylist(String str) {
ArrayList<Character> charList = new ArrayList<Character>();
for(int i = 0; i<str.length();i++){
charList.add(str.charAt(i));
}
return charList;
}
But i see a string array in your example, so if you wanted to convert a string array into ArrayList use this:
public static ArrayList<String> convertStringArrayToArraylist(String[] strArr){
ArrayList<String> stringList = new ArrayList<String>();
for (String s : strArr) {
stringList.add(s);
}
return stringList;
}
Let's take a question : Reverse a String. I shall do this using stream().collect(). But first I shall change the string into an ArrayList .
public class StringReverse1 {
public static void main(String[] args) {
String a = "Gini Gina Proti";
List<String> list = new ArrayList<String>(Arrays.asList(a.split("")));
list.stream()
.collect(Collectors.toCollection( LinkedList :: new ))
.descendingIterator()
.forEachRemaining(System.out::println);
}}
/*
The output :
i
t
o
r
P
a
n
i
G
i
n
i
G
*/
This is using Gson in Kotlin
val listString = "[uno,dos,tres,cuatro,cinco]"
val gson = Gson()
val lista = gson.fromJson(listString , Array<String>::class.java).toList()
Log.e("GSON", lista[0])
I recommend use the StringTokenizer, is very efficient
List<String> list = new ArrayList<>();
StringTokenizer token = new StringTokenizer(value, LIST_SEPARATOR);
while (token.hasMoreTokens()) {
list.add(token.nextToken());
}
If you're using guava (and you should be, see effective java item #15):
ImmutableList<String> list = ImmutableList.copyOf(s.split(","));

How to get index of an item in java.util.Set

I know the differences between Set and List(unique vs. duplications allowed, not ordered/ordered, etc). What I'm looking for is a set that keeps the elements ordered(that's easy), but I also need to be able to recover the index in which an element was inserted. So if I insert four elements, then I want to be able to know the order in which one of them was inserted.
MySet<String> set = MySet<String>();
set.add("one");
set.add("two");
set.add("three");
set.add("four");
int index = set.getIndex("two");
So at any given moment I can check if a String was already added, and get the index of the string in the set. Is there anything like this, or I need to implement it myself?
After creating Set just convert it to List and get by index from List:
Set<String> stringsSet = new HashSet<>();
stringsSet.add("string1");
stringsSet.add("string2");
List<String> stringsList = new ArrayList<>(stringsSet);
stringsList.get(0); // "string1";
stringsList.get(1); // "string2";
A small static custom method in a Util class would help:
public static <T> int getIndex(Set<T> set, T value) {
int result = 0;
for (T entry:set) {
if (entry.equals(value)) return result;
result++;
}
return -1;
}
If you need/want one class that is a Set and offers a getIndex() method, I strongly suggest to implement a new Set and use the decorator pattern:
public class IndexAwareSet<T> implements Set {
private Set<T> set;
public IndexAwareSet(Set<T> set) {
this.set = set;
}
// ... implement all methods from Set and delegate to the internal Set
public int getIndex(T entry) {
int result = 0;
for (T entry:set) {
if (entry.equals(value)) return result;
result++;
}
return -1;
}
}
you can extend LinkedHashSet adding your desired getIndex() method. It's 15 minutes to implement and test it. Just go through the set using iterator and counter, check the object for equality. If found, return the counter.
One solution (though not very pretty) is to use Apache common List/Set mutation
import org.apache.commons.collections.list.SetUniqueList;
final List<Long> vertexes=SetUniqueList.setUniqueList(new LinkedList<>());
it is a list without duplicates
https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.2/index.html?org/apache/commons/collections/list/SetUniqueList.html
How about add the strings to a hashtable where the value is an index:
Hashtable<String, Integer> itemIndex = new Hashtable<>();
itemIndex.put("First String",1);
itemIndex.put("Second String",2);
itemIndex.put("Third String",3);
int indexOfThirdString = itemIndex.get("Third String");
you can send your set data to a new list
Java ArrayList<String> myList = new ArrayList<>(); myList.addAll(uniqueNameSet); myList.indexOf("xxx");

Categories

Resources