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().
Related
I want to replace single object from List<String> with multiple objects.
List<String> list = new ArrayList<>(Arrays.asList("ROLL_NO","FULL_NAME","PERCENTAGE", "ADDRESS"));
I want to replace "FULL_NAME" with "FIRST_NAME" AND "LAST_NAME". So my list elements will be like as
"ROLL_NO",
"FIRST_NAME",
"LAST_NAME",
"PERCENTAGE",
"ADDRESS"
Collections.replaceAll() method replaces with single object only.
Is there a better way with java8 stream?
Thanks in advance.
Remove the FULL_NAME element and replace it with the FIRST_NAME and LAST_NAME elements:
List<String> list = new ArrayList<>(Arrays.asList("ROLL_NO","FULL_NAME","PERCENTAGE", "ADDRESS"));
int index = list.indexOf("FULL_NAME");
list.remove(index); //remove "FULL_NAME"
list.add(index, "LAST_NAME");
list.add(index, "FIRST_NAME");
Note the order which I am adding them. First LAST_NAME and then FIRST_NAME. This is done as setting an element at in index shifts the current element at that index to the right of the list. By doing so the elements are in the correct order as you suggested in the question.
To solve your problem, you can use remove() and add(). But a better approach will be creating a class to hold all those attributes:
public class Person{
private String rollNo;
private String firstName;
private String lastName;
private double percentage;
private String double;
//your constructors, getters & setters
}
Then use an ArrayList to hold various Person object together as one collection:
ArrayList<Person> list = new ArrayList<>();
This way, whenever you need to add/remove a record as a whole, there is no need to add/remove all related attributes manually which is very prone to mistakes.
If you list is mutable, you can use a listIterator to accomplish the same thing.
import java.util.ArrayList;
import java.util.List;
class Scratch {
public static void main(String[] args) {
final var values = new ArrayList<>(List.of(args));
final var it = values.listIterator();
while (it.hasNext()) {
final var value = it.next();
if ("FULL_NAME".equals(value)) {
it.remove();
it.add("FIRST_NAME");
it.add("LAST_NAME");
}
}
}
}
I have two Lists and trying to form a String with element from each List, and in between when I do " ", the sorted order is maintained. But once I put "|" in the middle, which I would want to, the order of the elements in the Set gets switched around.
How can I add "|" and still maintain the sorted order in the Set students?
Here is the code:
Set<String> students = new HashSet<>();
Set<String> fn = new HashSet<>();
Set<String> nums = new HashSet<>();
List<String> firstNames = new ArrayList<>(fn);
Collections.sort(firstNames);
List<String> favNumbers = new ArrayList<>(nums);
Collections.sort(favNumbers);
for(int i=0; i<firstNames.size(); i++) {
students.add(firstNames.get(i) + "|" + favNumbers.get(i));
}
System.out.println(students);
With ... + " " + ..., the order is [Joshua 4, Lyon 7], but if "|" is added in place of " ", the order becomes [Lyon|7, Joshua|4] when I want and should be[Joshua|4, Lyon|7].
A HashSet does not provide any ordering guarantees about its contents, using whatever ordering the underlying HashMap generates, which is in turn based on the hashCode() of the elements.
When you change the contents of a string, you get a different hash code--simple as that. The order in a HashMap is undefined and could change if you inserted additional elements triggering a rehash.
If you want a set with a guaranteed order, you can use a SortedSet implementation (such as TreeSet), but you'd need to write a proper class and implement suitable Comparators. Alternately, you could use LinkedHashSet, which maintains elements in insertion order at the expense of additional overhead.
You should be using object oriented design, as Java is an object oriented language. Instead of trying to represent the various features of a student as independent collection, create a Student POJO which contains these features. Then, create custom comparators to sort by either name or favorite number.
public class Student {
private String firstName;
private String lastName;
private int favNumber;
// getters and setters
public static Comparator<Student> NameComparator
= new Comparator<Student>() {
public int compare(Student s1, Student s2) {
String f1 = s1.getFirstName();
String f2 = s2.getFirstName();
String l1 = s1.getLastName();
String l2 = s2.getLastName();
if (l1.equalsIgnoreCase(l2) {
return f1.toUpperCase().compareTo(f2);
}
else {
return l1.toUpperCase().compareTo(l2);
}
}
};
public static Comparator<Student> FavComparator
= new Comparator<Student>() {
public int compare(Student s1, Student s2) {
return s1.getFavNumber() < s2.getFavNumber();
}
};
}
Now if you have a list of students, List<Student> list, you can sort via:
Collections.sort(list, Student.NameComparator);
Or, to sort by favorite numbers, use:
Collections.sort(list, Student.FavComparator);
From the documentation for HashSet:
It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
So you cannot rely on HashSet to preserve any kind of order.
It looks to me like you just need to preserve the order of insertion, in which case you're better off not using a Set and rather a List, e.g.,
List<String> students = new ArrayList<>();
Sorry if the title isn't clear, I wasn't sure how to word it. I have an arraylist of objects and within each of these objects I store an integer value referring to a category and one referring to an ID.
I want to find the number of unique combinations of category and IDs that there are.
So at the moment I have
for(Object object: listofObjects){
//For each unique type of object.getID
//For each unique type of object.getCategory
//Add 1 to counter
}
I can't figure out how to do this. Doing things like for(int cat: object.getCategory()) brings up an error.
I can add the values to a new list within the initial for each loop like so,
ArrayList<Integer> aList= new ArrayList<Integer>();
for (Object object : spriteExplore) {
aList.add(object.getCategory());
}
for (int cat : aList) {
testCounter++;
}
but this obviosuly does not take into account uniqueness and also makes it awkward for factoring in the other variable of ID.
I feel like there is probably some easier work around that I am missing. Any advice?
Thanks in advance.
So you list of UserDefine object in ArrayList and you want to find unique Object.Just create set from list.
For e.g Suppose you have
List<Customer> list=new ArrayList<Custeomer>();
list.add(new Customer("A",12));
list.add(new Customer("B",13));
list.add(new Customer("A",12));
now
create set From this list
Set<Customer> set = new HashSet<Customer>(list);
this will have unique Customer
IMP : dont forget to override equals and hashcode method for Customer
Your best approach would be storing the data correctly.
It's possible that you still need to store non-unique items, if that's so - continue using an ArrayList, but in addition, use the following:
Override the hashcode & equels function as shown in this link:
What issues should be considered when overriding equals and hashCode in Java?
Then, use a Set (HashSet would probably be enough for you) to store all your objects. This data structure will disregard elements which are not unique to elements already inside the set.
Then, all you need to do is query the size of the set, and that gives you the amount of unique elements in the list.
I don't know any library that does this automatically, but you can do it manually using sets. Sets will retain only unique object so if you try to add the same value twice it will only keep one reference.
Set<Integer> categories = new HashSet<Integer>();
Set<Integer> ids= new HashSet<Integer>();
for (Object object : listofObjects) {
categories.add(object.getCategory());
ids.add(object.getID());
}
Then you get the number of unique categories / ids by doing
categories.size()
ids.size()
And all your unique values are stored in the sets if you want to use them.
I would look into using a (Hash)Map<Integer, Integer>. Then just have 1 foreach loop, checking to see if the value of Map<object.getId(), object.getCategory()> is null by checking if map.get(object.getId()) is null - if it is, then this pair does not exist yet, so add this pair into the map by using map.put(object.getId(), object.getCategory()). If not, do nothing. Then at the end, to find the number of unique pairs you can just use map.size()
Hope this helps
Map<Integer,List<Integer>> uniqueCombinations = new HashMap<Integer,List<Integer>>();
for (Object object : listofObjects) {
if(uniqueCombinations.get(object.getCategoryId())==null) {
uniqueCombinations.put(object.getCategoryId(), new LinkedList<Integer>);
}
uniqueCombinations.get(object.getCategoryId()).add(object.getId());
}
return uniqueCombinations.size()
I believe you want unique combinations of both category and id, right?
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class SO {
class MyObject{
private int id;
private int category;
private String name;
private MyObject(int id, int category,String name) {
super();
this.id = id;
this.category = category;
this.name = name;
}
protected int getId() {
return id;
}
protected int getCategory() {
return category;
}
#Override
public String toString() {
return "MyObject [id=" + id + ", category=" + category + ", name=" + name + "]";
}
}
public static void main(String[] args) {
SO so = new SO();
List<Object> listofObjects = new ArrayList<Object>();
listofObjects.add(so.new MyObject(1,1,"One"));
listofObjects.add(so.new MyObject(1,1,"Two"));
listofObjects.add(so.new MyObject(1,2,"Three"));
Map<String,List<MyObject>> combinations = new HashMap<String,List<MyObject>>();
for(Object object: listofObjects ){
//For each unique type of object.getID
//For each unique type of object.getCategory
//Add 1 to counter
if (object instanceof MyObject){
MyObject obj = (MyObject)object;
String unique = obj.id+"-"+obj.category;
if (combinations.get(unique) == null){
combinations.put(unique, new ArrayList<MyObject>());
}
combinations.get(unique).add(obj);
}
}
System.out.println(combinations);
//counts
for(Entry<String,List<MyObject>> entry:combinations.entrySet()){
System.out.println(entry.getKey()+"="+entry.getValue().size());
}
}
}
Use the Hashmap to save occurence. Dont forget to implement hashcode und equals Methods. You can generate them if you work with Eclipse IDE.
public static void main(String[] args) {
List<MyObject> myObjects = Arrays.asList(new MyObject(1, 2), new MyObject(2, 3), new MyObject(3, 4), new MyObject(3, 4));
Map<MyObject, Integer> map = new HashMap<>();
for (MyObject myObject : myObjects) {
Integer counter = map.get(myObject);
if(counter == null){
counter = 1;
} else {
counter = counter + 1;
}
map.put(myObject, counter);
}
long uniqueness = 0;
for(Integer i : map.values()){
if(i == 1){
++uniqueness;
}
}
System.out.println(uniqueness);
}
The last part can be replaced by this one line expression if you are working with Java 8:
long uniqueness = map.values().stream().filter(i -> i == 1).count();
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, ...);
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");