I have a list of array lists. Each list in the main list contains constant number of items. (Say 3 items in each array list)
. What I want to do is I need to get the indexwise sum of each list as a new List.
for example If my main List contains array lists like
1, 2, 3
1, 2, 3
1, 2, 3
then my resultant list should be
3, 6, 9
and I have to do this with RxJava only. Since I am very new to RxJava I'm confused with wich operators I should use. I tried many ways but since those are not working I'm not posting with question. If anyone could suggest a hint or suggestion it would be very helpful. Thanks in advance
My source list is
List<ArrayList<Integer>> mainList;
and I need a resultant List<Integer> sumList
This is not really the main purpose of RxJava but you can do this via zip:
List<List<Integer>> lists = new ArrayList<>();
for (int i = 0; i < 3; i++) {
lists.add(Arrays.asList(1, 2, 3));
}
Flowable<Integer> f = Flowable.zip(lists, a -> {
int sum = 0;
for (Object o : a) {
sum += (Integer)o;
}
return sum;
})
// as individual items
f.test()
.assertResult(3, 6, 9);
// as one list
f.toList()
.test()
.assertResult(Arrays.asList(3, 6, 9));
1)You should add the following RxMath dependency in your build.gradle (app level).
compile 'io.reactivex:rxjava-math:1.0.0'
2) Use the following code to add sum of integer values from an Array or List.
int totalCount = MathObservable.sumInteger(Observable.just(classesItemList)
.flatMapIterable(new Func1<List<ClassesItem>, Iterable<? extends ClassesItem>>() {
#Override
public Iterable<? extends ClassesItem> call(List<ClassesItem> list) {
return list;
}
})
.map(new Func1<ClassesItem, Integer>() {
#Override
public Integer call(ClassesItem classesItem) {
return classesItem != null ? classesItem.getStudentsCount() : 0;
}
})).toBlocking().single();
3) use the total count wherever you want.
Related
I have to return a list of lists with LiveData.
The background is, that I load some data out of my Room database.
The database call depends on a counter. So I tried the following approach:
MediatorLiveData<List<List<Foo>> forView = new MediatorLiveData<>();
forView.addSource(counter, (trigger) -> {
List<List<Foo>> output = new LinkedList<>();
for(int i = 0; i < counter; i++) {
output.add(new ArrayList<>());
forView.addSource(repository.getDataForCounter(i), (data) -> {
//With some workaround I thought I've access to the position
output.remove("i");
output.add("i", data);
});
}
return output;
});
I think the workaround for the index didn't work, because the variables in lambdas have to be implicit final.
Is there any other approach to "merge" a variable number of lists got out of a database in one list of such lists?
I'm adding three different objects to an ArrayList, but the list contains three copies of the last object I added.
For example:
for (Foo f : list) {
System.out.println(f.getValue());
}
Expected:
0
1
2
Actual:
2
2
2
What mistake have I made?
Note: this is designed to be a canonical Q&A for the numerous similar issues that arise on this site.
This problem has two typical causes:
Static fields used by the objects you stored in the list
Accidentally adding the same object to the list
Static Fields
If the objects in your list store data in static fields, each object in your list will appear to be the same because they hold the same values. Consider the class below:
public class Foo {
private static int value;
// ^^^^^^------------ - Here's the problem!
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
In that example, there is only one int value which is shared between all instances of Foo because it is declared static. (See "Understanding Class Members" tutorial.)
If you add multiple Foo objects to a list using the code below, each instance will return 3 from a call to getValue():
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
The solution is simple - don't use the static keywords for fields in your class unless you actually want the values shared between every instance of that class.
Adding the Same Object
If you add a temporary variable to a list, you must create a new instance of the object you are adding, each time you loop. Consider the following erroneous code snippet:
List<Foo> list = new ArrayList<Foo>();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Here, the tmp object was constructed outside the loop. As a result, the same object instance is being added to the list three times. The instance will hold the value 2, because that was the value passed during the last call to setValue().
To fix this, just move the object construction inside the loop:
List<Foo> list = new ArrayList<Foo>();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo(); // <-- fresh instance!
tmp.setValue(i);
list.add(tmp);
}
Your problem is with the type static which requires a new initialization every time a loop is iterated. If you are in a loop it is better to keep the concrete initialization inside the loop.
List<Object> objects = new ArrayList<>();
for (int i = 0; i < length_you_want; i++) {
SomeStaticClass myStaticObject = new SomeStaticClass();
myStaticObject.tag = i;
// Do stuff with myStaticObject
objects.add(myStaticClass);
}
Instead of:
List<Object> objects = new ArrayList<>();
SomeStaticClass myStaticObject = new SomeStaticClass();
for (int i = 0; i < length; i++) {
myStaticObject.tag = i;
// Do stuff with myStaticObject
objects.add(myStaticClass);
// This will duplicate the last item "length" times
}
Here tag is a variable in SomeStaticClass to check the validity of the above snippet; you can have some other implementation based on your use case.
Had the same trouble with the calendar instance.
Wrong code:
Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++) {
myCalendar.add(Calendar.DAY_OF_YEAR, 1);
// In the next line lies the error
Calendar newCal = myCalendar;
calendarList.add(newCal);
}
You have to create a NEW object of the calendar, which can be done with calendar.clone();
Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++) {
myCalendar.add(Calendar.DAY_OF_YEAR, 1);
// RIGHT WAY
Calendar newCal = (Calendar) myCalendar.clone();
calendarList.add(newCal);
}
Every time you add an object to an ArrayList, make sure you add a new object and not already used object. What is happening is that when you add the same 1 copy of object, that same object is added to different positions in an ArrayList. And when you make change to one, because the same copy is added over and over again, all the copies get affected.
For example,
Say you have an ArrayList like this:
ArrayList<Card> list = new ArrayList<Card>();
Card c = new Card();
Now if you add this Card c to list, it will be added no problem. It will be saved at location 0. But, when you save the same Card c in the list, it will be saved at location 1. So remember that you added same 1 object to two different locations in a list. Now if you make a change that Card object c, the objects in a list at location 0 and 1 will also reflect that change, because they are the same object.
One solution would be to make a constructor in Card class, that accepts another Card object. Then in that constructor, you can set the properties like this:
public Card(Card c){
this.property1 = c.getProperty1();
this.property2 = c.getProperty2();
... //add all the properties that you have in this class Card this way
}
And lets say you have the same 1 copy of Card, so at the time of adding a new object, you can do this:
list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
It can also consequence of using the same reference instead of using a new one.
List<Foo> list = new ArrayList<Foo>();
setdata();
......
public void setdata(int i) {
Foo temp = new Foo();
tmp.setValue(i);
list.add(tmp);
}
Instead of:
List<Foo> list = new ArrayList<Foo>();
Foo temp = new Foo();
setdata();
......
public void setdata(int i) {
tmp.setValue(i);
list.add(tmp);
}
I am having 2 arraylist , arraylist are field from web-service
I have to compare arraylist and find un-common value from both
Arraylist is dynamic and changing continious
What i have done is :
for (int i = 0; i < arraylist.size(); i++) {
for (int j = 0; j < arraylist1.size(); j++) {
if ((arraylist.get(i).get("alert_id")).equals(arraylist1.get(j).get("alert_id")))
{
Log.e("Same", "faltu");
}
else {
Log.e("not same", "not faltu");
}
}
}
value :
arraylist 1 = id=92
arraylist 2 =id1 92
arraylist 1 = id1=91
arraylist 2 =id1 91
arraylist 1 = id1=86
arraylist 2 =id1 86
arraylist 1 =id1=85
arraylist 2 =id1 85
arraylist 1 = id1=84
arraylist 2 =id1 84
arraylist 1 = id1=81
arraylist 2 =id1 81
arraylist 1 =id1=80
arraylist 2 =id1 80
arraylist 1 = id1=79
arraylist 2 =id1 79
First you had to loop the two arraylist and you had to check whether the values are equal (OR) not. If the values are not equal, then it has to be added in the separate list and before adding to the list make sure the last value it is checked till the last value in the inner loop. The below code describes the sample process,
ArrayList<String> unCommonList = new ArrayyList<String>();
for (int i= 0; i<arraylist.size();i++) {
for (int j= 0; j<arraylist1.size();j++) {
if (!arrayList.get(i).equal(arraylist1..get(j))) {
//Checking whether the last value in the list..
if (j == (arrayList1.Size() - 1)) {
unCommonList.add(arrayList.get(i));
}
}
}
}
/* Try this one */
ArrayList<Integer> arrayList=new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
ArrayList<Integer> arrayListtwo=new ArrayList<>();
arrayListtwo.add(1);
arrayListtwo.add(3);
arrayListtwo.add(4);
arrayListtwo.add(6);
for(int i=0;i<arrayList.size();i++){
for(int j=0;i<arrayListtwo.size();j++){
if(arrayListtwo.get(j).equals(arrayList.get(i))){
Log.e("equal",""+arrayList.get(i));
}else{
Log.e("unequal",""+arrayList.get(i));
}
}
}
List<Integer> A1 = new ArrayList<Integer>();
A1.add(1);
A1.add(6);
A1.add(3);
A1.add(9);
List<Integer> B1 = new ArrayList<Integer>();
B1.add(3);
B1.add(6);
You should be better off calling remove(Object obj) with each element in the collection containing objects to be removed. This method removes the first instance of obj so if you want to remove all occurrences you will have to take care of that. If the object has been found and removed successfully it returns a true otherwise a false is returned.
Hope this is what you were looking for?
List<Integer> A1MinusB1 = new ArrayList<Integer>(A1);
A1MinusB1.removeAll(B1);
And the result will be
Results:
1
9
Or
You can do this.
// Make the two lists
List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
List<Integer> list2 = Arrays.asList(2, 3, 4, 6, 7);
// Prepare a union
List<Integer> union = new ArrayList<Integer>(list1);
union.addAll(list2);
// Prepare an intersection
List<Integer> intersection = new ArrayList<Integer>(list1);
intersection.retainAll(list2);
// Subtract the intersection from the union
union.removeAll(intersection);
// Print the result
for (Integer n : union) {
System.out.println(n);
}
You can use HashMap.put() method.
If it returns any value means a key value pair already exists. If it returns null means no Key-Value pair exists.
This is most efficient way to find duplicates.
I have list of integer IDs. Lets say this list is ArrayList<Integer> or int[], it doesn't matter. I have another ArrayList<Obj> that contains the objects with the same ids like in the first list, but they are ordered in different order.
I want to order the objects in the second list in the order as the ids in the first list.
EXAMPLE:
FIRST LIST: { 1, 5, 4, 8, 6 }
SECOND LIST: { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] }
RESULT LIST: { Obj[id=1], Obj[id=5], Obj[id=4], Obj[id=8], Obj[id=6] }
Can someone tell me an (efficient) way to do this?
I would suggest using a map:
Map<Integer, Obj> map = new HashMap<Integer, Obj>(secondList.size() * 2);
for (final Obj obj : secondList) {
map.put(obj.id, obj);
}
for (int i = 0; i < secondList.size(); i++) {
secondList.set(i, map.get(firstList.get(i)));
}
This runs in O(n), which IMHO is pretty much the best you can get.
A/ Create a matching id index list, such as:
1 -> 0
5 -> 1
4 -> 2
8 -> 3
6 -> 4
That's a reversed reference of your first list. It indicates the position of each id. A SparseIntArray is a good way of doing it:
SparseIntArray ref = new SparseIntArray();
for (int i = 0; i < firstList.size(); i++) {
ref.append(firstList.get(i), i);
}
Then you need to sort your second list using a Comparator that uses the id of the Object and the ref table:
Collections.sort(secondList, new Comparator<Obj>() {
public int compare(Obj t1, Obj t2) {
return ref.get(t1.id) - ref.get(t2.id);
}
});
I was in the middle of writing Etienne's answer when he posted it, so just for fun here's an O(N^2) solution with a smaller constant factor that doesn't create any objects:
int[] first = { 1, 5, 4, 8, 6 };
Obj[] second = { Obj[id=5], Obj[id=8], Obj[id=6], Obj[id=1], Obj[id=4] };
int i = 0;
while(i < second.length) {
int ind = -1;
for(int j=0;j<first.length;j+=1) {
if(first[j] == second[i].id) {
ind = j;
break;
}
}
if(ind == -1) break; //Bad news
if(ind == i) {
i += 1;
} else {
Obj temp = second[i];
second[i] = second[ind];
second[ind] = temp;
}
}
Obviously the creation of second[] is pseudocode, but the rest will work if the arrays are equal length. I think this will be a little bit faster than Etienne's for very small data sets, but you'd have to profile both answers.
Dear all i am comparing two List in android if both values are same and it is returning true that is fine but i want to know how many values have been correct between the list string if it is not matching how to achieve this Help is appreciated. Below is my code.
List<String> list1 = new ArrayList<String>(i1.values());
///list 1 = [-ful; to be full of; play; playful; full of play]
List<String> acct_Rte_Cdes_A = Arrays.asList(result) ;
///acct_Rte_Cdes_A = [-ful; to be full of; play; playful; full of play]
if (list1.equals(acct_Rte_Cdes_A)) {
// do what you want to do if the string is there
//System.out.println("True");
} else {
System.out.println("False");
}
Use Collection#retainAll(). like
List<Integer> common = new ArrayList<Integer>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.
So you can check for size if it is greater than 0 it meanse some elements are common. And which are common elements common will tell.
You can use containsAll method on Java collection. Here is an example.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String[] a) {
String elements[] = { "A", "B", "C", "D", "E" };
List<String> list = new ArrayList<String>(Arrays.asList(elements));
elements = new String[] { "A", "B", "C" };
List<String> list2 = new ArrayList<String>(Arrays.asList(elements));
System.out.println(list.containsAll(list2)); // true
System.out.println(list2.containsAll(list)); // false
}
}
Otherwise, you can use apache CollectionUtils library to improve performances. Depending on the type of Collection provided, this method will be much faster than calling Collection.containsAll(Collection) instead.
See the doc of apache containsAll here.
int correctCount=0, incorrectCount = 0;
List<String> list1 = new ArrayList<String>(i1.values());
List<String> acct_Rte_Cdes_A = Arrays.asList(result)
for(String tmp1: list1) {
for(String tmp2: list2) {
if(tmp1.compareTo(tmp2) == 0) {
correctCount++;
} else {
incorrectCount++;
}
}
}
it's time complexity is high but it will do the trick.
You can iterate through the lists yourself checking for equality and at the same time keeping a counter to indicate on which position they differ.
Sample (pseudo) code:
//if equal return 0, else position of difference
//keep in mind that item at index [0] is first, so return would be 1 if lists differ there
public int checkEquality(List list1, List list2) {
for (int i = 0; i < list1.size(); ++i) {
if (list1[i] != list2[i])
return i + 1;
}
return 0;
}
Also keep in mind, that you'd have to check if the lists are of the same size, and decide what to do if they are not (for example, return -1 to indicated this).
list1.containsAll(acct_Rte_Cdes_A)
boolean containsAll(Collection<?> c)
Returns true if this list contains all of the elements of the
specified collection.