I have an array where i get the values as names of some students and the array is dynamically populates and it does not contain static values. Now what i want to check is that whether the array obtained has any same name. Here is some part of my code,
ArrayList<Student> rows;
for (Student name: rows) {
}
I dont know how to check. I have used compartor but it didnt work. Can anyone help. Inside the array I will get all student names
Use a list to store any duplicate names:
List<String> dups = new ArrayList<>();
and a set where you will store names:
Set<String> names = new HashSet<>();
A set contains only unique values.
Now iterate through your list
(I guess your Student class has a method like getName() to obtain the student's name):
for (Student student : rows) {
String studentname = student.getName();
if (!names.add(studentname) {
dups.add(studentname);
}
}
The method names.add() returns false when it's not possible for an item to be added to the set because it already exists in it.
So when it returns false it encountered a duplicate name and the name is added to the dups list.
When this loop finishes, you can find all the duplicate student names in the dups list and show them in a toast:
if (dups.size() > 0) {
StringBuilder sb = new StringBuilder("There are duplicates: ");
for (String studentname : dups) {
sb.append(studentname).append(", ");
}
String msg = sb.toString();
msg = msg.substring(0, msg.length() - 2);
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
A way to check it is to convert your list to a set and check if the size got reduced (because Sets do not accept duplicate values), something like :
ArrayList<Student> rows;
Set<Student> set = new HashSet<Student>(rows);
if(set.size() < rows.size()){
// In this case you have repeated values in the list
}
Note that it depends on your equals method of the Student class to determine how Students are compared, so since you are checking againist their names you might have this equals method inside your Student class:
#Override
public boolean equals(Object obj) {
if( obj instanceof Student) {
return (obj.name.equals(name));
}
return false;
}
Store the data in HashMap with key as studentName and value as student object
Map studentMap = new HashMap<>()
If you add the data with same key again , the data gets updated
studentMap.put(studentName, Student)
To check if key exists and update accordingly
if(studentMap.containsKey(studentName)){
// logic if key already exists
}else{
//logic if key doesn't exists
}
If you want list instead of map , then get list from map
List studentList = new ArrayList(studentMap.values())
Check this sample java class used to count no of duplicate elements.
public class CountDuplicate {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
arrayList.add("bbb");
arrayList.add("ccc");
arrayList.add("aaa");
arrayList.add("ccc");
arrayList.add("bbb");
HashSet<String> hsUnique = new HashSet<String>(arrayList);
for (String str : hsUnique) {
System.out.println(Collections.frequency(arrayList, str) +" times "+ str);
}
}
}
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.
what i'm trying to do with the method below is look for a specific student in an array list that where the name and unique number(HUN) match the key and keyInt respectively. Once that student is found it should add to the local array list returnStudent and return it. However the line returnStudent.add(student(i)); is giving me an error and i can't figure out how to fix it,i need it to add the specific student to the local array list.
public ArrayList<Student1> searchByKey(String key, int keyInt)
{
ArrayList<Student1> returnStudent = new ArrayList<Student1>();
Student1 student = new Student1(key);
int i = 0;
while(i <= students.size())
{
if(student.getName().equals(key) && student.getHUN() == keyInt)
{
return Student.add(student(i));
}
i=i+1;
}
return returnStudent;
}
Thanks in advance.
Change
returnStudent.add(student(i));
to
returnStudent.add(student); // student is the element
to add to a specific index, use -
returnStudent.add(i, student); // i is the index to add element at
Note - since you have initialized i=0 you shall iterate through i < students.size() or you might end up accessing get(i) on the list for the value that doesn't exist (base indexed to 0).
The other way to do what you are trying to achieve is using Java8 as -
ArrayList<Student1> students = new ArrayList<>();
public ArrayList<Student1> searchByKey(String key, int keyInt) {
ArrayList<Student1> returnStudent = new ArrayList<>();
Student1 student = new Student1(key);
students.forEach(element -> {
if (element.getName().equals(key) && element.getHUN() == keyInt) {
returnStudent.add(element);
}
});
return returnStudent;
}
Assuming students is an ArrayList with prepopulated data, you can do the following.
public ArrayList<Student1> searchByKey(String key, int keyInt) {
ArrayList<Student1> returnStudent = new ArrayList<Student1>();
for(Student1 student1 : students) {
if(student1.getName().equals(key) && student1.getHUN() == keyInt) {
returnStudent.add(student1);
}
}
return returnStudent;
}
I have changed the while loop to foreach loop to make it look simpler and easily understandable.
You loop through students. But add student(i). Note the s at the end. Change the add to students(i).
This function loops through a dictionary (allWords) and uses the
getKey function to generate a key. wordListMap is a HashMap> so I need to loop through and put the key and and a List. If there is not a list I put one if there is I just need to append the next dictionary word. This is where I need help. I just can't figure out the syntax to simply append the next word to the list that is already there. Any Help would be appreciated.
public static void constructWordListMap() {
wordListMap = new HashMap<>();
for (String w : allWords) {
int key = getKey(w);
if (isValidWord(w) && !wordListMap.containsKey(key)) {
List list = new ArrayList();
list.add(w);
wordListMap.put(key, list);
} else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
}
}
map.get(key).add(value)
Simple as that.
So I've gathered that you want to, given HashMap<Integer, List<String>>, you'd like to:
create a List object
add String objects to said List
add that List object as a value to be paired with a previously generated key (type Integer)
To do so, you'd want to first generate the key
Integer myKey = getKey(w);
Then, you'd enter a loop and add to a List object
List<String> myList = new List<String>;
for(int i = 0; i < intendedListLength; i++) {
String myEntry = //wherever you get your string from
myList.add(myEntry);
}
Lastly, you'd add the List to the HashMap
myHash.put(myKey, myList);
Leave any questions in the comments.
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.put(key, wordListMap.get(key).add(w));
}
If you want to add a new value to your list, you need to retrieve that list first. In the code above, you are putting the return value of add into the table (which is a boolean), and that is not what you want.
Instead, you will want to do as Paul said:
else if (isValidWord(w) && wordListMap.containsKey(key)) {
wordListMap.get(key).add(w);
}
The reason this works is because you already added an ArrayList to the table earlier. Here, you are getting that ArrayList, and adding a new value to it.
I am working with Arraylist of objects.
while i already succeeded in delete values from Arraylist while they are numeral.
i'm having trouble delete from arraylist while they are String
here is the example :
public class ArrayListDemo {
public static void main(String[] args) {
// create an empty array list with an initial capacity
ArrayList<Namer> arrlist = new ArrayList<Namer>( );
// use add() method to add values in the list
arrlist.add(new Namer("1","A","G"));
arrlist.add(new Namer("2","E","G"));
arrlist.add(new Namer("3","F","G"));
System.out.println("Size of list: " + arrlist.size());
// let us print all the values available in list
for (Namer value : arrlist) {
System.out.println("age = " + value.age);
}
arrlist.remove("3");
System.out.println("Now, Size of list: " + arrlist.size());
for (Namer value : arrlist) {
System.out.println("age = " + value.age); //System.out.println("Value = " + value);
}
}
}
and the result of running it proof it doesnt deleted the spesific row
i need to delete if with String and cant use number as "Key" .
Size of list: 3
age = 1
age = 2
age = 3
Now, Size of list: 3
age = 1
age = 2
age = 3
what can i make it to work with String in order to delete ?
if that's help
this is the object of arrayList
public class Namer
{
// instance variables - replace the example below with your own
public String age;
public String name;
public String L_name;
public Namer(String a, String na , String Lname)
{
// initialise instance variables
age =a;
name=na;
L_name=Lname;
}
}
You have Namer objects in your ArrayList, not Strings. When you call remove("3"), the ArrayList will look for an object that returns true when equals is called on it with "3". Of course, no String will compare equals with any Namer.
You must do the comparison yourself with the name field, and remove the appropriate item. This can be done with an Iterator and its remove method.
You have to use the object or the index to remove and you are not using either ...
Try this code :
arrlist.remove(2);
or
// create an empty array list with an initial capacity
ArrayList<Namer> arrlist = new ArrayList<Namer>( );
Namer namer1= new Namer("1","A","G");
Namer namer2= new Namer("2","E","G");
Namer namer3= new Namer("3","F","G");
// use add() method to add values in the list
arrlist.add(namer1);
arrlist.add(namer2);
arrlist.add(namer3);
arrlist.remove(namer3);
The method arrlist.remove(idx) takes as paramenter the (interger) index of the element to be removed from the array. There's no such thing as a "key" for ArrayLists.
You probably want to use java.util.Map<Integer,Namer>.
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();