I am trying to populate a RecyclerView with a custom adapter. This Adapter takes in a model that has setters and getters. This model contains three parameters: String username, int proPic, and int bckgImg. What i am trying to achieve is a RecyclerView with an alphabetical sorted list. I populate the model by using the following code:
private ArrayList<FriendsModel> friendsData = new ArrayList<>(0);
friendsData.add(new FriendModel("Erick", R.drawable.default_pro_pic, R.drawable bckgImg);
After i am done with populating 5 objects of the FriendModel, i then proceed to compare the characters found in the ArrayList:
for(char alph = 'A'; alph <= 'Z'; alph++){
List<String> friends = getFriends(alph);
if(friends.size() > 0){
//Populate the Sorted Alphabetical view
}
}
private List<String> getFriends(char alph) {
//Empty List used to populate when comparing existing model to alphabet
List<String> friends = new ArrayList<>();
//5 objects of FriendsData with three parameters
for (int i = 0; i < friendsData.size(); i++){
//If the first string parameter character at position 0 is equal to alph
if(friendsData.get(i).toString().charAt(0) == alph){
friends.add(friendsData.get(i).toString());
}
}
return friends;
}
I am not sure if i am doing this correctly, what is the adequate or correct way to compare the characters in an ArrayList based on its model?
Instead of using constructor to initialize the variables, always use the setter methods, such classes are also known as pojo(Plain old java objects) or VO(value objects).
Assuming your FriendModel class is like below..
public class FriendModel{
String username;
int proPic;
int bckgImg;
public FriendModel(){}
//redundant constructor, you can remove this since you are using setter methods now.
public FriendModel(String username, int proPic, int bckgImg){
this.username=username;
this.proPic=proPic;
this.bckgImg=bckgImg;
}
//you'll need the below getters and setters..
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getProPic() {
return proPic;
}
public void setProPic(int proPic) {
this.proPic = proPic;
}
public int getBckgImg() {
return bckgImg;
}
public void setBckgImg(int bckgImg) {
this.bckgImg = bckgImg;
}
}
And where ever you are doing the following,
for(char alph = 'A'; alph <= 'Z'; alph++){
List<String> friends = getFriends(alph);
if(friends.size() > 0){
//Populate the Sorted Alphabetical view
}
}
private List<String> getFriends(char alph) {
//Empty List used to populate when comparing existing model to alphabet
List<String> friends = new ArrayList<>();
//5 objects of FriendsData with three parameters
for (int i = 0; i < friendsData.size(); i++){
//If the first string parameter character at position 0 is equal to alph
String username=friendsData.get(i).getUsername(); //get the username
if(username.charAt(0) == alph){ //compare the username with charater in alph variable
friends.add(username); //add in another list
}
}
return friends;
}
Custom Comparator should help
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
});
or if it's not work so us it
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
The proper way to sort the list with model is to define Comparator. For your current example you used use.
Collections.sort(friendsData, new Comparator<FriendsModel>() {
#Override
public int compare(FriendsModel obj1, FriendsModel obj2) {
return obj1.getUsername.compareTo(obj2.getUsername); //For Ascending order
//OR
return obj2.getUsername.compareTo(obj1.getUsername); //For Descending order
}
});
"compare" function compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
Related
I have an arraylist that looks like this:
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
I store groups of 2 persons in a pair. For example:
[Person1, Person2]
[Person3, Person4]
The algorithm I use right now still makes duplicates, I've tried out hashmaps and iterating through them with for loop but they just give me back the original list.
This is the code:
package com.company;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class createGroups
{
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
public static void main(String[] args){
//Define names
String[] names = {"Person1", "Person2", "Person3", "Person4"};
try
{
//Create combinations. In a try catch because of the saveFile method.
combination(names, 0, 2);
//Print all the pairs in the Arraylist x
printPairs();
} catch (IOException e)
{
e.printStackTrace();
}
}
static void combination(String[] data, int offset, int group_size) throws IOException
{
if(offset >= data.length)
{
//Create new Arraylist called foo
ArrayList<String[]> foo = new ArrayList<>();
//Create a pair of 2 (data.length = 4 / group_size = 2)
for(int i = 0; i < data.length / group_size; i++)
{
//Add the pair to foo.
foo.add(Arrays.copyOfRange(data, 2 * i, 2 * (i + 1)));
}
//Add foo to x
x.add(foo);
//saveFile(foo);
}
for(int i = offset; i < data.length; i++){
for(int j = i + 1; j < data.length; j++){
swap(data, offset, i);
swap(data, offset + 1, j);
combination(data, offset + group_size, group_size);
swap(data, offset + 1, j);
swap(data, offset, i);
}
}
}
public static void printPairs(){
//Print all pairs
for(ArrayList<String[]> q : x){
for(String[] s : q){
System.out.println(Arrays.toString(s));
}
System.out.println("\n");
}
}
private static void swap(String[] data, int a, int b){
//swap the data around.
String t = data[a];
data[a] = data[b];
data[b] = t;
}
}
The output right now is this:
Output
Every group of 4 names is a 'list' of pairs (Not really a list but that's what I call it)
And this is the desired output:
Desired output
But then you can see that the first and the last list of pairs are basically the same how do I change that in my combination method
The question:
How can I change my combination method so that it doesn't create duplicate groups.
And how can I make the list smaller (The desired output) when printing the created lists.
If I wasn't clear enough or if I didn't explain what I want very well, let me know. I'll try to make it clearer.
Create an object similar to this. It takes 4 strings (2 pairs). Puts the strings into array and sorts this array. That means any combination of strings you put in will be converted into one sorted combination, but the object internaly remembers which person is person1, person2, ...
private class TwoPairs {
private final String person1;
private final String person2;
private final String person3;
private final String person4;
private final String[] persons;
TwoPairs(String person1, String person2, String person3, String person4) {
this.person1 = person1;
this.person2 = person2;
this.person3 = person3;
this.person4 = person4;
persons = new String[4];
persons[0] = person1;
persons[1] = person2;
persons[2] = person3;
persons[3] = person4;
// if we sort array of persons it will convert
// any input combination into single (sorted) combination
Arrays.sort(persons); // sort on 4 objects should be fast
// hashCode and equals will be comparing this sorted array
// and ignore the actual order of inputs
}
// compute hashcode from sorted array
#Override
public int hashCode() {
return Arrays.hashCode(persons);
}
// objects with equal persons arrays are considered equal
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
TwoPairs other = (TwoPairs) obj;
if (!Arrays.equals(persons, other.persons)) return false;
return true;
}
// add methods which you might need
// getters for individual persons
// String getPerson1() { return person1; }
// or perhaps pairs of persons
// String[] getPair1() { return new String[] {person1, person2}; }
// add sensible toString method if you need it
}
Your ArrayList x will change like this
ArrayList<TwoPairs> x = new ArrayList<TwoPairs>();
before adding new TwoPairs object into x check if this list already contains this object.
if (!x.contains(twoPairsObject)) {
x.add(twoPairsObject);
}
I've been trying everything to sort out this array and seem not working. Every Examobject in the array has String firstName, String lastName, int ID, char examType('M' or 'F'), and int score. The array should be sorted by the first examType -'M' followed immediately by the final 'F' of the same person. Also having trouble with the line if(position[i*2].getID() == r[i+1].getID()). Total 10 objects. I tried to match the exam objects by the ID but still not working. ONLY one loop is allowed!
public static Exam[] collateExams(Exam[] exams)
{
Exam [] r = new Exam[10];
r = exams;
//Exam [] finalExam = new Exam[50];
int[] position = new int[10];
for(int i = 0; i < exams.length; i++)
{
if(r[i].getExamType() == 'M')
{
r[i*2] = new Exam(r[i*2].getFirstName(), r[i*2].getLastName(),
r[i*2].getID(), r[i*2].getExamType(), r[i*2].getScore());
position[i*2] = r[i*2].getID();
if(position[i*2].getID() == r[i+1].getID())
r[i+1] = new Exam(r[i+1].getFirstName(), r[i+1].getLastName(),
r[i+1].getID(), r[i+1].getExamType(), r[i+1].getScore());
}
/*if((r[i].getExamType() == 'F') && (position[i] == r[i].getID()))
{
}*/
}
return r;
}
}
something like this:
class ExamComparator implements Comparator {
public int compare(Exam e1, Exam e2) {
return e1.getExamType() == e2.getExamType() ? 0 : (e1.getExamType() == 'F' ? 1 : -1);
}
}
Arrays.sort(exams, new ExamComparator());
Use Arrays.sort with your custom Comparator which will use values you want.
As #djechlin explained you can use ,Arrays.sort with your own custom comparator like mentioned in below example , You can use List or Array whatever you want its upto you ,
List<String> list=Arrays.asList("XYZ","ABC","DEF");
String [] stringArray=new String[]{"XYZ","ABC","DEF"};
Arrays.sort(stringArray,new Comparator(){
public int compare(Object one,Object two){
String first=(String)one;
String second=(String)two;
return first.compareTo(second);
}
});
for(String s:stringArray){
System.out.print(s+"\t");
}
Collections.sort(list,new Comparator(){
public int compare(Object one,Object two){
String first=(String)one;
String second=(String)two;
return first.compareTo(second);
}
});
System.out.println(list);
Output
ABC DEF XYZ // for Arrays.sort
[ABC DEF XYZ]// for Collections.sort
Now Coming to your actuall problem
The array should be sorted by the first examType -'M' followed
immediately by the final 'F' of the same person
You have to create your own custom comparator which does the sorting based on examType
I have an ArrayList in Java :
{"PatMic", "PatientDoc", "Phram", "Patnet", "PatientA"}
All the elements have a number assigned : PatMic = 20, PatientDoc = 30, Phram = 40, Patnet = 50, PatientA = 60.
And my current Comparator :
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(final String o1, final String o2) {
final int numbr1 = getElementNumber(); //Returns element's number in a list
final int numbr2 = getElementNumber();
if (numbr1 > numbr2 ) {
return 1;
} else if (numbr1 < numbr2 ) {
return -1;
}
return 0;
}
};
Collections.sort(strings, comparator);
I do not want to change the assigned numbers to each element but would want to move the element PatientA in between PatMic and PatientDoc so the modified list should look like :
{"PatMic", "PatientA" "PatientDoc", "Phram", "Patnet"}
Could someone please suggest how to achieve this? I tried many ways to modify the existing Comparator logic but in vain. Thank you.
You are trying to sort based on some inherent value associated with a String. Therefore, sorting on a String itself is probably not correct. What you probably want to use is either a custom object (implement equals, hashCode and the interface Comparable), or an enum type. This will allow you to change the internal state of these objects explicitly, which will manifest itself naturally when using a Comparator. For example, using a class:
class MyClass implements Comparable
{
private String name;
private int value;
//Constructor
public MyClass(String s, int v)
{
name = s;
value = v;
}
//Getters and setters
//Implement comparing method
}
Then you can use these objects in place of your Strings:
//...
MyClass patMic = new MyClass("PatMic", 20);
// So on..
First, you should give you comparator sufficient knowledge about what it should do. I mean you should have some data available to comparator that says something like "okay, sort them all by associated number except this one - place it right here". "Right here" could be anything that points exact position, I gonna choose "before that element".
So here we go
public void sortWithException(List<String> data, final Map<String, Integer> numbers, final String element, final String next) {
Collections.sort(data, new Comparator<String>() {
#Override
public int compare(String first, String second) {
if (first.equals(element) || second.equals(element)) { //the exception
Integer nextNumber = numbers.get(next);
Integer firstNumber = numbers.get(first);
Integer secondNumber = numbers.get(second);
if (first.equals(element)) {
if (next == null) // placing the exception after ANY element
return 1;
return secondNumber >= nextNumber ? -1 : 1; //placing the element before next and after all next's predecessors
} else { // second.equals(element)
if (next == null)
return -1;
return firstNumber >= nextNumber ? 1 : -1;
}
} else { //normal sort
return numbers.get(first) - numbers.get(second);
}
}
});
}
and call it like sortWithException(data, numbers, "PatientA", "PatientDoc")
Note that i used Map for associated numbers, you should probably use your own method to get those numbers.
I need to know the way to find the second largest element among an array of objects. for eg.
if there is an array of objects of a Book class with attributes like book name, price, in stock quantity
Book[] b=new Book[];
b[0]=new Book("x",200,50);
b[1]=new Book("y",100,44);
b[2]=new Book("z",500,29);
How can we list the book with second largest price along with other attributes like name and in stock quantity
Make a List of Books from it, sort it using Collections.sort and take the element on index 1.
List<Book> booklist = new ArrayList<Book>(Arrays.asList(b));
Collections.sort(booklist, new Comparator<Book>() {
#Override
public int compare(Book o1, Book o2) {
return o2.getPrice() - o1.getPrice();
}
});
if (booklist.size() > 1) {
System.out.println(booklist.get(1));
}
You can loop through this Array to find the largest and with this the second largest Element of the Array. Because the Elements are Objects you have to get the Value that you want to compare from the element with a getter or the variable is public in the objects.
public int getSecondLargest(Object[] obj){
int length = obj.length;
int largest = 0;
int secondLargest = 0;
for(int i = 0; i<length; i++){
if(obj[largest].getValue() <= obj[i].getValue()){
secondLargest = largest;
largst = i;
}
}
return secondLargest;
}
I think you should implements Interface Comparable.
and then use Collections.sort();
Implements a Comparator And sort your array, then pick second element.
class BookPriceComparator implements Comparator<Book> {
#Override
public int compare(Book a, Book b) {
return a.getPrice() - b.getPrice();
}
}
Arrays.sort(bookArr, new BookPriceComparator ());
import java.util.*;
//here you can make changes or you can create your own new class
//to sort book according to pages
class sortPrice implements Comparator<Test> {
public int compare(Test i1, Test i2) {
Integer x = i1.getPrice(), y = i2.getPrice();
return y.compareTo(x); // <--- changed
}
}
// in your case Test class could be Book class
public class Test {
/**
* #param args
*/
int price , page ;
String name;
Test(String n , int p ,int pg){
name=n;
price=p;
page=pg;
}
public String toString(){
return name+" "+price +" "+page ;
}
public String getName(){
return name;
}
public int getPage(){
return page;
}
public int getPrice(){
return price;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Test[] b=new Test[3];
b[0]=new Test("x",200,50);
b[1]=new Test("y",100,44);
b[2]=new Test("z",500,29);
ArrayList<Test> a = new ArrayList<>();
for(int i=0;i<3;i++){
a.add(b[i]);
}
sortPrice s= new sortPrice(); // required to pass as argument to tell
//based on which sorting order you want to sort
Collections.sort(a,s ); //here we are sorting Test(Book) based on price.
System.out.println(a.get(1)); // printing arrayList //<----- changed
}
}
I have two List of array string. I want to be able to create a New List (newList) by combining the 2 lists. But it must meet these 3 conditions:
1) Copy the contents of store_inventory into newList.
2) Then if the item names in store_inventory & new_acquisitions match, just add the two quantities together and change it in newList.
3) If new_acquisitions has a new item that does not exist in store_inventory, then add it to the newList.
The titles for the CSV list are: Item Name, Quantity, Cost, Price.
The List contains an string[] of item name, quantity, cost and price for each row.
CSVReader from = new CSVReader(new FileReader("/test/new_acquisitions.csv"));
List <String[]> acquisitions = from.readAll();
CSVReader to = new CSVReader(new FileReader("/test/store_inventory.csv"));
List <String[]> inventory = to.readAll();
List <String[]> newList;
Any code to get me started would be great! =]
this is what i have so far...
for (int i = 0; i < acquisitions.size(); i++) {
temp1 = acquisitions.get(i);
for (int j = 1; j < inventory.size(); j++) {
temp2 = inventory.get(j);
if (temp1[0].equals(temp2[0])) {
//if match found... do something?
//break out of loop
}
}
//if new item found... do something?
}
I would start by building the newList as a HashMap or TreeMap instead of a List. This makes it easy to search for the matching record. Furthermore, I would convert the String[] to a custom object (e.g. Record) that contains the name, quantity, cost and price field. This would take care of copying the information. The you could try something like this:
Map<String, Record> newMap = new TreeMap<String, Record>();
for(String[] ss : acquisitions) {
Record rec = Record.parse(ss); // For requirement (1)
newMap.put(rec.getName(), rec);
}
for(String[] ss : inventory) {
Record rec = Record.parse(ss); // For requirement (1)
if(newMap.containsKey(rec.getName())) {
// For requirement (2)
// The mergeWith method can then add quantities together
newMap.get(rec.getName()).mergeWith(rec);
} else {
// For requirement (3)
newMap.put(rec.getName(), rec);
}
}
edit
An extra advantage of having a Record object, is that it can be printed to screen much easier by implementing the toString function.
public class Record implements Comparable<Record> {
public static Record parse(String[] ss) {
// TODO: implement some basic parsing
}
private String name;
private int quantity;
private BigDecimal cost, price;
private Record() {}
public String getName() { return name; }
public int getQuantity() { return quantity; }
public BigDecimal getCost() { return cost; }
public BigDecimal getPrice() { return price; }
public int compareTo(Record other) {
return this.name.compareTo(other.name);
}
public String toString() {
return name;
}
}