so I have to create a Matrix class that will generically combine different objects in an array. I know I can do this by checking the types but I want to find a better way. This has to work on Doubles, Integers, Floats, Shorts, Longs, Strings, etc. Here is my current code for this:
public class Matrix<E>{
private E mat2[];
private static final int SIZE = 4;
public Matrix(){
mat2 = (E[]) new Object[SIZE];
}
public Matrix(E a1, E a2, E b1, E b2){
mat2 = (E[]) new Object[SIZE];
mat2[0] = a1;
mat2[1] = a2;
mat2[2] = b1;
mat2[3] = b2;
}
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
Double tmp = ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
}
}
public E getElement(int index){ return mat2[index];}
public String toString(){
String info = "[";
for(int i = 0; i < SIZE; i++){
info += "\t" + mat2[i];
info += (i % 2 == 1) ? "\t]\n[" : "";
}
return info.substring(0, info.length() - 1);
}
public static void main(String... arg){
Matrix<Integer> matInt = new Matrix<Integer>(new Integer(1), new Integer(0), new Integer(0), new Integer(1));
Matrix<Integer> matInt2 = new Matrix<Integer>(new Integer(1), new Integer(0), new Integer(0), new Integer(1));
System.out.println(matInt);
Matrix<String> matStr = new Matrix<String>("One", "Two", "Three", "Four");
System.out.println(matStr);
matInt.add(matInt2);
System.out.println(matInt);
}
}
Now let me draw your attention to this method:
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
Double tmp = ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
}
}
I am assuming Double right now so that if it is a floating point number, it will maintain the decimal but if it isn't I was hoping to cut it off. I can easily accomplish what I need by doing something along the lines of:
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
if(type == Double){
Double tmp ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
if(type == Integer){
//do integer instead
}
if(type == String){
//do String instead
}
}
}
}
but I am wondering if I can find a more Generic war of doing this without all the checks. The program is for an assignment so I must use generics. The idea is to be able to add and multiply the types in the array 'mat2'. So if I have Integer types they need to add together. If I have Strings they need to add together as well.
Related
I've an ArrayList which contains pairs of integers( say int i, int j). But it may be contains duplicates pairs (like (int i, int j) and (int j, int i)). Now how can I remove duplicates from it in O(n) time complexity.
Updated code:
class Pair<t1,t2>
{
int i, j;
Pair(int i,int j){
this.i=i;
this.j=j;
}
}
public class My
{
public static void main(String[] args) {
Pair p;
List<Pair<Integer,Integer>> src = Arrays.asList(new Pair(1,2),
new Pair(2,3), new Pair(2,1),new Pair(1,2));
HashSet<String> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
p=src.get(i);
if(dest.contains(p.j+" "+p.i)) {
System.out.println("duplicacy");
}
else {
dest.add(p.i+" "+p.j);
}
}
System.out.println("set is = "+dest);
List<Pair<Integer,Integer>> ans=new ArrayList();
String temp;
int i,j;
Iterator<String> it=dest.iterator();
while(it.hasNext())
{
temp=it.next();
i=Integer.parseInt(temp.substring(0,temp.indexOf(' ')));
j=Integer.parseInt(temp.substring(temp.indexOf('
')+1,temp.length()));
ans.add(new Pair(i,j));
}
for(Pair i_p:ans) {
System.out.println("Pair = "+i_p.i+" , "+i_p.j);
}
}//end of main method
}//end of class My
This code is working fine but I want to know it performance wise, I mean its overall time complexity ?
If you can modify Pair class, just implement equals() and hashCode():
public class Pair {
private int a;
private int b;
public Pair(int a, int b) {
this.a = a;
this.b = b;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
return (a == pair.a && b == pair.b) || (a == pair.b && b == pair.a);
}
#Override
public int hashCode() {
return Objects.hashCode(new HashSet<>(Arrays.asList(a,b)));
}
#Override
public String toString() {
return "Pair{" +
"a=" + a +
", b=" + b +
'}';
}
}
Then just create a new Set<Pair>:
List<Pair> pairs = Arrays.asList(new Pair(1, 2), new Pair(2, 1), new Pair(3, 2));
Set<Pair> pairSet = new HashSet<>(pairs);
System.out.println(pairSet);
Output:
[Pair{a=1, b=2}, Pair{a=3, b=2}]
If you can't modify Pair class:
List<Pair> pairs = Arrays.asList(new Pair(1, 2), new Pair(2, 1), new Pair(3, 2));
Set<Pair> pairSet = pairs.stream()
.map(pair -> new HashSet<>(Arrays.asList(pair.getA(), pair.getB())))
.distinct()
.map(integers -> {
Iterator<Integer> iterator = integers.stream().iterator();
return new Pair(iterator.next(), iterator.next());
})
.collect(Collectors.toSet());
System.out.println(pairSet);
Output:
[Pair{a=1, b=2}, Pair{a=2, b=3}]
If you want, you can convert your Set back to a list:
List<Pair> list = new ArrayList<>(set);
But it's most likely unnecessary.
Make only one loop throught list of Pairs and collect by the way in HashSet processed pair and it's reversed copy:
List<Pair<Integer,Integer>> lp = Arrays.asList(new Pair(1,2),
new Pair(2,3),
new Pair(1,2),
new Pair(2,1));
Set<Pair<Integer,Integer>> sp = new HashSet<>();
List<Pair<Integer,Integer>> ulp = lp.stream()
.collect(ArrayList::new,
(l,p)-> { Pair<Integer,Integer> p1 = new Pair(p.getValue(), p.getKey());
if (!(sp.contains(p))&&!(sp.contains(p1))){
l.add(p);
sp.add(p);
sp.add(p1);
}} , List::addAll);
System.out.println(ulp);
Since the contains() of HashSet runs in O(1) time (See this and other references) you can use the following method which is the overall O(n):
import java.util.*;
import javafx.util.*;
public class Main
{
public static void main(String[] args) {
List<Pair<Integer,Integer>> src = Arrays.asList(new Pair(1,2), new Pair(2,3), new Pair(2,1));
HashSet<Pair<Integer,Integer>> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
if(dest.contains(src.get(i)) ||
dest.contains(new Pair(src.get(i).getValue(),src.get(i).getKey()))) {
}else {
dest.add(src.get(i));
}
}
System.out.println(dest);
}
}
EDIT 1:
You can use Map.Entry instead of javafx.util.pair. Do the program without Javafx is as follow.
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Map.Entry<Integer,Integer>> src = Arrays.asList(new AbstractMap.SimpleEntry(1,2),
new AbstractMap.SimpleEntry(2,3), new AbstractMap.SimpleEntry(2,1));
HashSet<Map.Entry<Integer,Integer>> dest = new HashSet();
for(int i=0; i < src.size(); i++) {
if(dest.contains(src.get(i)) ||
dest.contains(new AbstractMap.SimpleEntry(src.get(i).getValue(),src.get(i).getKey()))) {
}else {
dest.add(src.get(i));
}
}
System.out.println(dest);
}
}
I have this HashMap:
HashMap< itemDetails, Pair<ArrayList<itemDetails>, AssociatedInfo>> AssociatedItemCasuaList = new HashMap<>();
where its key is class, and its values consist of pair (a= arraylist of class itemDetails, b= class AssociatedInfo):
class itemDetails {
public ArrayList<Integer> itemId;
public float expectedSupport = 0;
// etc
}
and
class Pair<T, U> {
T a;
U b;
Pair(T a, U b) {
this.a = a;
this.b = b;
}
T getA() {
return a;
}
U getB() {
return b;
}
}
and
class AssociatedInfo {
public int noOfKCasual = 0;
public int AssociateListStart = 0;
public int AssociateListEnd = 0;
}
I want to sort the first pair of the the values of HashMap
which is the ArrayList<Integer> itemId in the class itemDetails
I used this Comparator
public class ItemComparator implements Comparator<ArrayList<Integer> >{
#Override
public int compare(final ArrayList<Integer> entry1, final ArrayList<Integer> entry2){
if (entry1 == null && entry2 == null)
return 0;
if (entry1 == null)
return 1;
if (entry2 == null)
return -1;
if (entry1.isEmpty() && entry2.isEmpty())
return 0;
if (entry1.isEmpty())
return 1;
if (entry2.isEmpty())
return -1;
return entry1.get(0).compareTo(entry2.get(0));
}
}
I don't know how to write Collections.sort
if (AssociatedItemCasuaList.containsKey(LHS)) {
AssociatedItemCasuaList.get(LHS).a.add(RHS2);
AssociatedItemCasuaList.get(LHS).b.AssociateListStart = 0;
AssociatedItemCasuaList.get(LHS).b.AssociateListEnd += 1;
AssociatedItemCasuaList.get(LHS).b.noOfKCasual += 1;
} else {
ArrayList<itemDetails> ArrayListRHS = new ArrayList<itemDetails>();
ArrayListRHS.add(RHS2);
AssociatedInfo AttribAssociatedInfo1 = new AssociatedInfo();
AttribAssociatedInfo1.noOfKCasual = 1;
AttribAssociatedInfo1.AssociateListStart = 0;
AttribAssociatedInfo1.AssociateListEnd = 0;
AssociatedItemCasuaList.put(LHS, new Pair(ArrayListRHS, AttribAssociatedInfo1));
}
// Collections.sort(AssociatedItemCasuaList.get(LHS), new ItemComparator());
Update:
Example:
AssociatedItemCasuaList < **key**=LHS, **value**=Pair<a, b> >
Let key=LHS:
LHS.itemId=1
LHS.expectedSupport=87.5
and values = Pair < a, b >
Let focus here in a only in this example.
a= ArrayList<itemDetails>
Let itemDetails RH2
and every time (in loop) I add RHS2 to key LHS as:
AssociatedItemCasuaList.get(LHS).a.add(RHS2)
here RHS2 takes different values every time
RHS2.itemId
RHS2.expectedSupport
until now, I don't have problem.
I want to sort the ArrayList in a (that I filled with RHS2) based on its itemId
Ignoring the fact I didn't understand a single word, what about this:
public class ItemComparator2 implements Comparator<itemDetails> {
Comparator myComp = new ItemComparator();
#Override
public int compare(itemDetails a, itemDetails b){
return myComp.compare(a.itemId, b.itemId);
}
}
// ...
Collections.sort(AssociatedItemCasuaList.get(LHS).getA(), new ItemComparator2());
I need to call GetNewItem function million times;
Items XY = GetNewItem(X, Y);
Items XYZ = GetNewItem(XY, Z);
Items XZ = GetNewItem(X, Z);
Items YZ = GetNewItem(Y, Z);
This function aims to
1- find intersection between ArrayList of structure namely
ArrayList<Records> RecordLists
2- and it also calculates the probability for the new ArrayList , this is my code:
class Records {
public int RecordId;
public double Prob;
}
class Items {
public ArrayList<Integer> itemId;
public ArrayList<Records> RecordLists;
public double ItemProb = 0.0;
};
private ArrayList<Records> Intersection(ArrayList<Records> list1, ArrayList<Records> list2) {
ArrayList<Records> Result = new ArrayList<>();
int i = 0, j = 0;
while (i < list1.size() && j < list2.size()) {
if (list1.get(i).RecordId== (list2.get(j).RecordId)) {
Records RecordDetails= new Records();
RecordDetails.RecordId= list1.get(i).RecordId;
RecordDetails.Prob+= 1;
Result.add(RecordDetails);
i++;
j++;
} else if (list1.get(i).RecordId < list2.get(j).RecordId) {
i++;
} else if (list1.get(i).RecordId > list2.get(j).RecordId) {
j++;
}
}
return Result;
}
public Items GetNewItem(Items item1, Items item2) {
Items NewItem = new Items ();
ArrayList<Integer> newItemId = new ArrayList<>();
newItemId.addAll(item1.itemId);
newItemId.addAll(item2.itemId);
NewItem.itemId = newItemId;
NewItem.RecordLists= Intersection(item1.RecordLists,item2.RecordLists);
NewItem.ItemProb = getProb(NewItem.RecordLists);
return NewItem ;
}
private double getProb(ArrayList<Records> RProb) {
double IProb = 0.0;
for (int i = 0; i < RProb.size(); i++) {
IProb += RProb.get(i).Prob;
}
return IProb ;
}
For this code I got 'out of memory error'
I don't know how to save the memory and time, I tried this solution:
java.lang.OutOfMemoryError: Java heap space with NetBeans
but my computer did freeze. I don't know what else I have to do.
Please use java conventions, e.g. variables in camel case, non public variables in classes (use getters/constructor/setters)
I'm not sure why are you getting the intersection that way, with that i and j variables.
Please try:
public <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
If you want to calculate something else maybe do it in a separate method?
Use floats instead of doubles.
Could you please paste whole code? I would like to reproduce this.
The following code performs 'hierarchical' sorting of a two-dimensional matrix. Firstly, it sorts elements based on the values of ranks. Secondly, it takes this sorted matrix, searches elements that have the same values of ranks, and sorts them based on dist. In descending order.
Question 1: Is it possible to achieve the same result in the easier way? I tried to create a Comparator, but it provided incorrect result for this particular case.
Question 2: How to get indexes of unsorted elements after sorting?
import java.util.ArrayList;
public class Test {
public static void main(String args[]) {
ArrayList<ArrayList<Double>> values = new ArrayList<ArrayList<Double>>();
ArrayList<Double> ranks = new ArrayList<Double>();
ArrayList<Double> dist = new ArrayList<Double>();
ranks.add(8.0);
ranks.add(3.0);
ranks.add(8.0);
ranks.add(1.0);
dist.add(1.8);
dist.add(2.8);
dist.add(1.9);
dist.add(2.1);
values.add(0,ranks);
values.add(1,dist);
int len = ranks.size();
ArrayList<ArrayList<Double>> sortedranks = new ArrayList<ArrayList<Double>>();
sortedranks = order(values,0,ranks.size());
boolean swapped = true;
int j = 0;
double tmp1, tmp2;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < len - j; i++) {
double val1 = sortedranks.get(0).get(i);
double val2 = sortedranks.get(0).get(i+1);
if (val1==val2) {
if (sortedranks.get(1).get(i) < sortedranks.get(1).get(i+1)) {
tmp1 = sortedranks.get(1).get(i);
tmp2 = sortedranks.get(1).get(i+1);
sortedranks.get(1).remove(i);
sortedranks.get(1).remove(i);
sortedranks.get(1).add(i,tmp2);
sortedranks.get(1).add(i+1,tmp1);
swapped = true;
}
}
}
}
for (int i = 0; i < len; i++) {
System.out.println("Ranks " + i + " : " + sortedranks.get(0).get(i)
+ ", Distances : " + sortedranks.get(1).get(i));
}
}
public static ArrayList<ArrayList<Double>> order(ArrayList<ArrayList<Double>> values, int i_start, int i_fin) {
boolean swapped = true;
int j = 0;
int i_rank = 0;
int i_dist = 1;
double tmp1_rank, tmp2_rank, tmp1_dist, tmp2_dist;
while (swapped) {
swapped = false;
j++;
for (int i = i_start; i < i_fin - j; i++) {
if (values.get(i_rank).get(i) < values.get(i_rank).get(i+1)) {
tmp1_rank = values.get(i_rank).get(i);
tmp2_rank = values.get(i_rank).get(i+1);
tmp1_dist = values.get(i_dist).get(i);
tmp2_dist = values.get(i_dist).get(i+1);
values.get(i_rank).remove(i);
values.get(i_rank).remove(i);
values.get(i_dist).remove(i);
values.get(i_dist).remove(i);
values.get(i_rank).add(i,tmp2_rank);
values.get(i_rank).add(i+1,tmp1_rank);
values.get(i_dist).add(i,tmp2_dist);
values.get(i_dist).add(i+1,tmp1_dist);
swapped = true;
}
}
}
return values;
}
}
The code that uses Comparator (does not work for my case):
public class MyEntry implements Comparable<MyEntry> {
private Double rank;
private Double dist;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
}
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
Double rfirst = value1.rank;
Double rsecond = value2.rank;
Double dfirst = value1.dist;
Double dsecond = value2.dist;
if (rsecond != rfirst) {
return (int) (rsecond - rfirst);
}
else {
return (int) (dsecond - dfirst);
}
}
};
}
Your Comperator approach would work, but is has a few bugs.
First of all I would replace the Doubles in MyEntry by double.
Comparing Double is not the same as comparing double
For example:
Double a = 1.0;
Double b = 1.0;
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.doubleValue()== b.doubleValue());
Will return
false
true
true
Then in the comparison you cast to int, but this implies flooring that data.
(int) (2 - 1.9) will give 0
Better is to compare using < and return -1 or 1.
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
double rfirst = value1.rank;
double rsecond = value2.rank;
double dfirst = value1.dist;
double dsecond = value2.dist;
if (rsecond != rfirst) {
return rsecond < rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond < dfirst ?-1:1;
}
return 0;
}
}
For your second question you require an index. This could be done in two ways. First option is to include the index in MyEntry like this:
public class MyEntry implements Comparable<MyEntry> {
private double rank;
private double dist;
private int index;
private static int nextIndex = 0;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
this.index = nextIndex++;
}
This way you will be able to retain the index but it is not so flexible.
A more flexible approach could be to have the index in a separate array, and sort that.
class IndexedArrayComparator implements Comparator<Integer>{
MyEntry[] array;
public IndexedArrayComparator(MyEntry[] entries){
this.array=entries;
}
public Integer[] createIndexes(){
Integer[] index = new Integer[array.length];
for(int i =0;i<index.length;i++){
index[i]=i;
}
return index;
}
public int compare(Integer i0, Integer i1) {
double rfirst = array[i0].rank;
double rsecond = array[i1].rank;
double dfirst = array[i0].dist;
double dsecond = array[i1].dist;
if (rsecond != rfirst) {
return rsecond > rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond > dfirst ?-1:1;
}
return 0;
}
}
You can then use it like this:
MyEntry[] entries = new MyEntry[5];
entries[0]= new MyEntry(1.1,5);
entries[1]= new MyEntry(1.1,4);
entries[2]= new MyEntry(2.1,5);
entries[3]= new MyEntry(0.1,3);
entries[4]= new MyEntry(3.1,1);
IndexedArrayComparator comp = new IndexedArrayComparator(entries);
Integer[] index = comp.createIndexes();
Arrays.sort(index,comp);
for(int i =0;i<index.length;i++){
MyEntry e = entries[index[i]];
System.out.println(String.format("%2d:r= %3.1f, d= %3.1f" ,index[i],e.rank,e.dist));
}
Which will give:
3:r= 0.1, d= 3.0
1:r= 1.1, d= 4.0
0:r= 1.1, d= 5.0
2:r= 2.1, d= 5.0
4:r= 3.1, d= 1.0
The second way of sorting while maintaining the index is also described here. Credits to Jon Skeet
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an arraylists filled with objects. Each object consists of two integers. How do i sort the arraylist based on the first integer while keeping the second integer with its original integer? And then how to I add all of the second integers of the sorted arraylist?
I tried this:
Collections.sort(info, new Comparator()
{
public int compare(M one, M two)
{
return m1.getCost().compareToIgnoreCase(m2.getCost());
}
});
class M{
//Declares the attributes belonging to this class
private int money;
private int cost;
//Constructor method
{
//this refers to object in which the method was called
this.cost = cost;
this.money = money;
}
//Returns the cost variable
public int getCost()
{
return cost;
}
public void setCost(int cost)
{
this.cost = cost;
}
//Returns the maximum amount
public int getMoney()
{
return money;
}
public void setMoney(int Money)
{
this.Money = Money;
}
}
I am new to java so any help would be greatly appreciated(:
import java.util.*;
public class M implements Comparator<M>{
int i,j;
M(int a, int b){
i=a; j=b;
}
public int compare(M m1, M m2){
return (m1.i-m2.i);
}
public boolean equals(Object o){
if(this.i==((M)o).i)
return true;
else
return false;
}
public static void main(String args[]){
M m1 = new M(2,1);
M m2 = new M(3,2);
M m3 = new M(1,3);
ArrayList<M> a = new ArrayList<M>();
a.add(m1);
a.add(m2);
a.add(m3);
Collections.sort(a,(Comparator<M>)m1);
//ArrayList a is sorted
for(int j=0;j<a.size();j++){
System.out.println(a.get(j).i);
}
}
}
Implement the Comparator interface in your class so that the Collections.sort method will sort the objects using the int1 of class M. Then use Collections.sort method to sort the array. This should answer the first part of the question.
When creating a Comparator it should be used as a Generic type with T (where T represents the objects in the array) and thus: public int compare(T a, T b) { .. }.
For instance:
new Comparator<M> {
// Note the signature
public int compare(M one, M two)
{
// Now return a correct value based on the ordering
// using one.getCost() and two.getCost()
// Obviously "compareToIgnoreCase" is wrong for use with numbers.
// Either work this out or see one of the existing/linked answers.
}
}
If generics are not used then the signature is public int compare(Object one, Object two) and casting will likely be needed - note that there is no overload for (int, int); it is a declared method that is never used!
See also:
How to sort an arraylist of objects by a property? (I have voted to close as a duplicate of this one and it shows a correct and simple way to get the ordering between two numeric values.)
Sorting an ArrayList of Contacts based on name? (Discusses another approach is to make the objects themselves implement Comparable.)
how about this :
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
M[] mm = new M[4];
mm[0] = new M(11, 2);
mm[1] = new M(11, 4);
mm[2] = new M(4, 67);
mm[3] = new M(4, 2);
mm = compareM(mm);
for (int a = 0; a < mm.length; a++) {
System.out.println("index : "+a+" a : "+mm[a].a+" b : "+mm[a].b);
}
}
public static M[] compareM(M[] data) {
for (int a = 0; a < data.length - 1; a++) {
for (int b = a + 1; b < data.length; b++) {
if (data[a].a > data[b].a) {
M temp = data[a];
data[a] = data[b];
data[b] = temp;
}
}
}
for (int a = 0; a < data.length; a++) {
int indStart = a;
int indEnd = a;
for (int b = a + 1; b < data.length; b++) {
if (data[b].a == data[a].a) {
indEnd++;
} else {
b = data.length;
}
}
a = indEnd;
for (int c = indStart; c <= indEnd; c++) {
for (int d = c + 1; d <= indEnd; d++) {
if (data[c].b > data[d].b) {
M temp = data[c];
data[c] = data[d];
data[d] = temp;
}
}
}
}
return data;
}
static class M {
public int a, b;
//u can have function to set value of a n b, or any function
public M(int ax, int bx) {
this.a = ax;
this.b = bx;
}
}
}