I have problem with comparing the value of array elements.
e.g. I wanted to compare the value of index 0 and index 2, and index 1 to index 3 and so on.
With the code below I suppose to get the result of numOfdifferentShape is 2 but I get 3.
How can I solve this problem? :-(
int numOfdifferentShape=0;
myArray = {40.0, 40.0, 40.0, 40.0, 80.0, 40.0, 40.0, 40.0}
for (int a=0; int a<myArray.size(); a=a+2)
{
for (int b=a+2; b<myArray.size; b=b+2)
{
if (!(myArray.get(a).equals(myArray.get(b) && myArray.get(a+1).equals(b+1)))
numOfdifferentShape++;
break;
}
}
There are several syntax errors in this code, but since TofuBeer has already pointed them out in the comments, I'll move on the the design and logic.
Going from the code, I'm assuming you don't have much experience with Java, and perhaps not with programming at all. So I'm going to go slowly here. I hope you aren't insulted by my explanations.
You say you are trying to find out how many of the objects which you are storing (as two ints) in your array are equal. To do this, you have to keep track of what unique objects you have already seen. Then you compare each object the list of unique objects and, if it doesn't match any of them, add it to the list. This is the basic algorithm.
Now, have you noticed that I keep using the word "object" in my description? When that happens, it usually means you should be making a class. I would make a simple one like this, holding the two integers:
class Box { // or whatever the objects are called
private final int height;
private final int width;
public Box(int h, int w) {
height = h;
width = w;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
#Override
public boolean equals(Object other) {
if (!(other instanceof Box))
return false;
Box b = (Box) other;
return b.height == height && b.width == width;
}
#Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + this.height;
hash = 97 * hash + this.width;
return hash;
}
}
Try to understand what each part of this code does (especially if this is actually your homework). Once you've got it, move on to the next part: doing the calculation that you were trying to do.
Let's say you have an array of Boxes, like this:
Box[] boxes = {
new Box(40, 40), new Box(40, 40), new Box(80, 40), new Box(40, 40)
};
(I can't tell if you're using an array or a list, so I'm just picking one to demonstrate.)
I already gave the algorithm for finding the number of unique items, so I'll show you how I would write it:
List<Box> unique = new ArrayList<Box>();
for (Box box : boxes) {
if (!unique.contains(box)) { // this is why I implemented equals() and hashCode()!
unique.add(box);
}
}
int numOfDifferentShape = unique.size();
This is much easier than trying to keep track of two ints for each object, plus it has the advantage that you can't get your array indices confused.
You could do this even more easily with a Set. It would look something like this:
Set<Box> boxSet = new HashSet<Box>();
for (Box b : boxes)
boxSet.add(b);
int numOfDifferentShape = boxSet.size();
Note that these last two snippets use features from Java 1.5, so I don't know if you've run into them before.
Does this make things clearer?
for (int i = 0; i < (myArray.size() - 2); ++i)
{
if (myArray[i] != myArray[i + 2])
++numOfdifferentShapes;
}
You have two loops, your description suggests you only want one.
You need to do bounds checking - do you want the n+2 to wrap to the start to the start of the array when it exceeds the length?
I think you have a parentheses problem. You wrote:
if (!(myArray.get(a).equals(myArray.get(b) && myArray.get(a+1).equals(b+1)))
when I think you mean:
if (!(myArray.get(a).equals(myArray.get(b)) && myArray.get(a+1).equals(b+1))
Also, in the same line, instead of:
equals(b+1)
don't you mean
myArray.get(b+1)
I have array list e.g.
{40,40,80,20,40,40} I wanted to
compare the elements. Even number of
index (e.g. index 0, index 2, index 4
etc) represents Height of an object
and Odd number of Index (e.g. index 1,
index 3 ec) represent Width of an
object. So, with the code above,
Object 1 (index 0 and 1).
Why not make an array of a Dimension class, something like this:
public class Dimension
{
private final int width;
private final int height;
public Dimension(final int w,
final int h)
{
width = w;
height = h;
}
public int getWidth()
{
return (width);
}
public int getHeight()
{
return (height);
}
}
then do a for loop something like this:
for(int i = 0; i < array.length; i += 2)
{
final Dimension a;
final Dimension b;
a = array[i];
b = array[i + 1];
// compare a.getLength() to b.getLength()
// or
// compare a.getWidth() to b.getWidth()
}
It is usually a bad idea to try and be "tricky" - saying even ones are with and odd ones are length is being tricky... bad idea IMO.
Related
I want to find all distinct triplets (a, b, c) in an array such that a + b + c = 0.
I implemented the algorithm in java but I am getting TLE when the input is large (for example 100,000 zeroes, etc).
For 100,000 zeroes, it should output (0, 0, 0) only.
Can someone give some idea about how to speed this up?
Below is the function which I have written. It takes an array as input and returns all unique triplets having the desired property as a list.
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ll = new ArrayList<List<Integer>>();
for(int i = 0; i < nums.length - 1; i++){
int x = nums[i];
int start = i + 1;
int end = nums.length - 1;
int sum = -x;
while(start < end){
int y = nums[start] + nums[end];
if(y == sum){
List<Integer> list = new ArrayList<Integer>();
list.add(nums[start]);
list.add(nums[end]);
list.add(x);
Collections.sort(list);
ll.add(list);
}
if(y < sum)
start++;
else
end--;
}
}
return ll.stream()
.distinct()
.collect(Collectors.toList());
}
I think that there is nothing you can do about the time complexity. Two indices must explore the array independently (except for starting/ending points), while the third can be constrained, like in your algorithm, which means that the complexity is O(n2). This dominates the preliminary sorting of the array, which is O(n·log(n)), and also a “demultiplication” step, which is O(n).
I wrote “demultiplication” because a “deduplication” is not desirable: suppose the array is [-1,-1,0,2]. Deduplicating it would eliminate the only solution. But a solution can't contain an integer more than twice, unless it's 0, in which case [0,0,0] is a solution. All integers appearing more than twice, or thrice in the case of 0, are redundant and can be eliminated in one pass after sorting and before the main algorithm.
As for the factor, it could be improved by limiting the exploration to what makes sense. I would modify your algorithm by making the pair of indices that you move until they meet, start outwards from where they meet, until the lower one hits the major index, or the upper one hits the end of the array. The starting point of the scan can be remembered across scans, adjusting it downwards as the major index moves upwards. If the starting point (actually a starting pair of adjacent indices) is outside the current range, the scan can be omitted tout court. Finding the initial starting point is an additional part of the algorithm which, after sorting, could be O(log(n)), but a very simple O(n) version would do just as well.
I have no time now to translate all the above into Java code, sorry. All I can do now is jot down the “demultiplication” code (untested) that goes right after the sorting of the array:
int len = 1;
int last = nums[0];
int count = 1;
for (int i = 1; i < nums.length; i++) {
int x = nums[i];
if (x != last) {
nums[len++] = x;
last = x;
count = 1;
} else if (count < 2 || x == 0 && count < 3) {
nums[len++] = x;
count++;
}
}
// use len instead of nums.length from this point on
The big time component I see, is that for the 100,000 zeroes example, you will hitting the if (y == sum) block for every single possible case. This appears to be the worst case for performance since you will never skip that block.
The largest improvement I can see is to first de-duplicate your input. Unfortunately sets won't work as we need still maintain up to three of the same entry. Thus, my recommendation is, after your sort, to loop through the input array and whenever you encounter more than three copies of a number in a row, remove the extras. They are not needed for the problem and just waste time.
You could create a List (an implementation of that is ArrayList) to store the combinations you already had. Always store a new value in the format of
a,b,c
where a <= b <= c
so, whenever you get a combination which may or may not already have been found, generate a String in the same format and check whether it is present in your List. If so, then do not add it. Otherwise add it to your List. After this you could convert the found values into numeric values. If you want to quicken it up, you could create a class like:
class XYZ {
public int x;
public int y;
public int z;
public XYZ(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public isMatch(int x, int y, int z) {
return (this.x == x) &&
(this.y == y) &&
(this.z == z);
}
public static boolean anyMatch(List<XYZ> list, int x, int y, int z) {
for (XYZ xyz : list) {
if (xyz.isMatch(x, y, z)) return true;
}
return false;
}
public static void addIfNotExists(List<XYZ> list, int x, int y, int z) {
if (!anyMatch(list, x, y, z)) list.add(new XYZ(x, y, z));
}
}
and you could use this class for your purpose, just make sure that x <= y <= z.
The filtering of non-unique triplets at the end can be eliminated by using a hash-table that stores the triplets in a sorted order, so all combinations of a triplet (with different ordering) gets stored exactly once.
Use a hashmap/hashset instead of an arraylist.
HashSet<List<Integer>> ll = new HashSet<List<Integer>>();
. . .
list.addAll(a,b,c)
Collections.sort(list)
ll.add(list)
In addition to this, You could also use another lookup table to ensure each repeating item in nums[] is used to calculate the triplets only once.
lookup_table = HashMap();
for(int i = 0; i < nums.length - 1; i++){
// we have already found triplets starting from nums[i]
// eg. [-1,-1,0,1], we don't need to calculate
// the same triplets for the second '-1'.
if (lookup_table.contains(nums[i]))
continue;
// Mark nums[i] as 'solved'
lookup_table.add(nums[i])
// usual processing here
int x = nums[i];
Or, since your nums[] list is already sorted, you could just skip repeating items, doing away the need for another lookup table.
i = 0;
while (i < nums.length - 1){
// we have already found triplets starting from nums[i]
// eg. [-1,-1,0,1], we don't need to calculate
// the same triplets for the second '-1'.
x = nums[i];
// skip repeating items
while (x == nums[i++]);
// usual processing here
. . .
i++;
}
and then you could just return the hashset as a list at the end.
So I've built this program to build different stair cases. Essentially the problem is: Given an integer N, how many different ways can you build the staircase. N is guaranteed to be larger than 3 and smaller than 200. Any previous step can not be larger than its following step otherwise it defeats the purpose of the staircase.
So given N = 3
You can build one staircase: 2 steps and then 1 step following that
Given N = 4
You can build one staircase: 3 steps and then 1 step following that
Given N = 5
You can build two staircases: 3 steps and then 2 steps OR 4 steps and then 1 step.
My method is below and it works, except its runtime is far too slow. So I was thinking of trying to make a memoization for the method, but to be honest I do not fully understand how to implement this. If I could get some help on how to do so that'd be great.
public static void main(String [] args)
{
System.out.println(answer(200));
}
public static int answer(int n) {
return bricks(1,n) -1;
}
public static int bricks(int height, int bricksLeft)
{
if(bricksLeft == 0)
{
return 1;
}
else if(bricksLeft < height)
{
return 0;
}
else
{
return bricks(height +1, bricksLeft - height) + bricks(height +1, bricksLeft);
}
}
Overview
So what you have here is a recursive solution. That works well for this type of problem. In this particular recursive solution, your recursive step will be called with the same arguments many times.
One really common optimization pattern for recursive solutions where the same calculation is being made many times is Dynamic Programming. The idea is that instead of doing the same calculation many times, we just cache each calculation the first time we do it. Then every following time, if we need to calculate the exact same value, we can just read the result from the cache.
Solution
With that in mind, this solution should work. It uses exactly the same logic as your original version, it just caches all results for the recursive step in a HashMap so that it never needs to calculate the same thing twice. It also uses a Staircase object to track pairs of (bricks, height). This is because we cannot insert pairs into a HashMap, we can only insert single objects.
Just change the variable bricks to whatever value you want to solve for.
public class Staircase {
private static HashMap<Staircase, Integer> cache;
public static void main(String[] args) {
cache = new HashMap<>();
int bricks = 6;
Staircase toBuild = new Staircase(1, bricks);
System.out.println(toBuild.waysToBuild() - 1);
}
public final int height;
public final int bricksLeft;
public Staircase(int height, int bricksLeft) {
this.height = height;
this.bricksLeft = bricksLeft;
}
public int waysToBuild() {
if (cache.containsKey(this)) {
return cache.get(this);
}
int toReturn;
if (bricksLeft == 0) {
toReturn = 1;
} else if (bricksLeft < height) {
toReturn = 0;
} else {
Staircase component1 = new Staircase(height + 1, bricksLeft - height);
Staircase component2 = new Staircase(height + 1, bricksLeft);
toReturn = component1.waysToBuild() + component2.waysToBuild();
}
cache.put(this, toReturn);
return toReturn;
}
#Override
public boolean equals(Object other) {
if (other instanceof Staircase) {
if (height != ((Staircase) other).height) {
return false;
}
if (bricksLeft != ((Staircase) other).bricksLeft) {
return false;
}
return true;
}
return false;
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + this.height;
hash = 73 * hash + this.bricksLeft;
return hash;
}
}
Analysis
I tested it out and the performance is much faster than your previous version. It computes values up to 200 instantly.
Your original function was O(2^n). That is because we make 2 recursive calls for each value from 1 to n, so the total number of calls is doubled for each time n is incremented.
The Dynamic Programming solution is O(n) since at most it will need to calculate the number of ways to make a staircase out of n bricks once for each value of n.
Additional Reading
Here is some more reading about Dynamic Programming: https://en.wikipedia.org/wiki/Dynamic_programming
Use a small class to hold the pairs (height, bricks), say:
private static class Stairs {
private int height;
private int bricks;
Stairs(int height, int bricks) {
this.height = height; this.bricks = bricks;
}
}
Then use a global HashMap<Stairs, Integer>, initialized in the main():
map = new HashMap<Stairs, Integer>();
In the bricks() function, check if the solution for a particular (height, bricks) pair is in the map. If yes, just return it from the map via a call to the get() method. Otherwise, do the computation:
Stairs stairsObj = new Stairs(height, bricks);
if(map.get(stairsObj) == null) {
// Put your compute code here
}
Before every return statement in the function, add two additional statements. Something like:
int result = <whatever you are returning right now>;
map.put(stairsObj, result);
return result;
I need to implement a "uniform crossover" genetic operator.
Edit: I realized that it is normal to have duplicates (because of random exchange) if a number appears in both individuals.
So I I added this:
if(anyDuplicate(p0_genome,minIndex) || anyDuplicate(p1_genome,minIndex)){
//rollback: swap again
swap(p0_genome,p1_genome,i);
}
but it stills create duplicates (most of time of the gene in position minIndex (which is excluded from the cycle!!!) . Of course I tested the function anyDuplicate,and it works very well
I tried with this code
> Note: Individual 1 and 2 have the same length but a different number
> of valid bits.
>
> Foe example: genotype length (of both individuals) = 10 ,
> representation as numbers from 1 to 10 without anyone repeated,the
> start delimiter is 1 and the end delimiter should be 2. Not used genes
> are = 0
>
> individual 1(p0_genome) = {1,4,5,3,2,0,0,0,0,0}
> individual 2(p1_genome) = {1,4,6,3,8,2,0,0,0,0}
Desideres output:
Individual 1(p0_genome): **1** <some genes ALL DIFFERENTS> **2** 0,0,0,.....
Individual 2(p1_genome): **1** <some genes ALL DIFFERENTS> **2** 0,0,0,.....
Main Code:
int indexOfLastP0 = findLast(p0_genome,gl); // last valid bit (the one = 2) of first individual
int indexOfLastP1 = findLast(p1_genome,gl); // last valid bit (the one = 2) of second individual
int minIndex = Math.min(indexOfLastP0,indexOfLastP1); // last valid bit of the "smaller" of the inviduals
// Building sons
/* exchange bit without considering delimiters bit (1 and 2)
and according to the smaller individual */
int threshold = 0.60;
for (int i=1; i<minIndex; i++) {
if (Math.Random()>threshold) {
swap(p0_genome,p1_genome,i);
}
// when exiting the loop the remaining of genes remain the same
Swap code:
public void swap(int[] array1, int[] array2 ,int i){
int aux=array1[i];
if (array2[i]!=2){
array1[i]=array2[i];
}
if (aux!=2){
array2[i]=aux;
}
anyDuplicate() code:
public boolean anyDuplicate(int[] genoma,int min){
for (int i=0;i<=min;i++){
for (int j=0;j<=min;j++){
if (genoma[i]==genoma[j] && i!=j){
return true;
}
}
}
return false;
}
findLast code:
public int findLast(int[] mgenome,int genotypeLength){
int k=1; // 1 element is not considered
while (k<genotypeLength && mgenome[k]!=0){
k++;
}
return k-1; // **I also tried returning k;**
}
The problem is that I get a lot of duplicates numbers in both individuals
I also tried with a "duplicate"(arraycopy from a parent to a child) of "fathers":
// Creating sons genotypes
int [] s0_genome = new int[gl];
int [] s1_genome = new int[gl];
// Building sons
int threshold = 0.60;
for (int i=0; i<minIndex; i++) {
if (Math.Random()>threshold)) {
s0_genome[i] = p1_genome[i];
s1_genome[i] = p0_genome[i];
}
else {
s0_genome[i] = p0_genome[i];
s1_genome[i] = p1_genome[i];
}
for (int i=minIndex; i<10; i++) {
// copy what's left
s0_genome[i] = p0_genome[i];
s1_genome[i] = p1_genome[i];
}
Am I doing something wrong? Thank you for any hint!
Okay, so you try swapping once, and if either of the resulting genomes contains duplicate values, you try swapping again. If there are still duplicates after the second try, you give up. This is not efficient, and the longer your genomes are, the more unlikely this is to work.
Solution A: You could try only doing a swap if the swapped value is not already in the target genome. That would give a swap function like this:
public void swap(int[] array1, int[] array2 ,int i){
int aux=array1[i];
if (array2[i]!=2 && !Arrays.asList(array1).contains(array2[i]){
array1[i]=array2[i];
}
if (aux!=2 && !Arrays.asList(array2).contains(array1[i]){
array2[i]=aux;
}
The problem with this is that it might completely lock genomes that contain the same values in different positions. For your example, with
g1 = {1, 4, 8, 9, 3, 2, 0, 0}
g2 = { 1, 3, 9, 8, 4, 2, 0, 0}
There would be no valid swaps at all, and the crossover would return the original genomes.
Solution B: If the value to be swapped is already present in the target genome, find the index of that gene in the target genome, and swap that too. This might cascade to require swaps in large parts of the genome, and of course it shouldn't happen when i=j.
Kind of depends on the desired behavior. For the example genomes above, what would a successful crossover look like?
I want to store 2 dimensional values i.e. B-1, C-2, D-3, etc.
Any suggestions on the classes or interfaces that can be used?
There are three basic types of multidimensional arrays:
Fixed. Think of a chess board, which is always 8x8 (variants notwithstanding). But this can also mean something that is variable but fixed upon instantiation;
Sparse. arrays where there are lots of empty space between values. Spreadsheets typically fit this description but what is and isn't sparse is typically a subjective judgement; and
Dense. The opposite of sparse. Most or all possible values are used.
Java doesn't have a native multidimensional array type. Java has arrays of arrays, which isn't quite the same thing. For example, this is legal Java:
int arr[][] = new int[] {
new int[3],
new int[4],
new int[5]
};
Fixed arrays can be done this way but it can be awkward. It's often easier to use a single dimensional array with an object wrapper:
public class Chessboard {
public final static DEFAULT_X = 8;
public final static DEFAULT_Y = 8;
public final static DEFAULT_SIZE = DEFAULT_X * DEFAULT_Y;
private final int x;
private final int y;
private final int size;
private final Piece squares[];
public Chessboard() {
this(DEFAULT_X, DEFAULT_Y);
}
public Chessboard(int x, int y) {
if (x < 2) {
throw new IllegalArgumentException("x (" + x + ") must be 2+");
}
if (y < 2) {
throw new IllegalArgumentException("y (" + y + ") must be 2+");
}
this.x = x;
this.y = y;
size = x * y;
pieces = new Piece[size];
}
public Piece get(int x, int y) {
return pieces[y * this.x + x];
}
public Piece get(String xy) {
// eg 'h3' => (7,2)
return get(xy.charAt(0) - 'a', xy.charAt(1) - '0');
}
// etc
}
This can of course be done with arrays of arrays instead.
Sparse arrays tend to be implemented in Java with maps:
public class Sparse2DArray<T> {
public final static int MAX_X = 8192;
public final static int MAX_Y = 8192;
private final Map<String, T> array = new HashMap<String, T>();
private final Pattern XY = Pattern.compile("^([A-Za-z]+)([0-9]+)");
public T get(int x, int y) {
if (x < 0 || x >= MAX_X) {
throw new IllegalArgumentException("x (" + x + ") must be 0 to " + (MAX_X-1));
}
if (y < 0 || y >= MAX_Y) {
throw new IllegalArgumentException("y (" + y + ") must be 0 to " + (MAX_Y-1));
}
return array.get(x + "," + y);
}
public T get(String xy) {
Matcher m = XY.matcher(xy);
if (!m.matches()) {
throw new IllegalArgumentException("xy (" + xy + ") must be letters followed by digits");
}
String s = m.group(1).toUpperCase();
int multiplier = 1;
int x = 0;
for (int i=s.length()-1; i>=0; i--) {
x += (s.chartAt(i) - 'A') * multiplier;
multiplier *= 26;
}
int y = Integer.valueOf(m.group(2));
return array.get(x, y);
}
// etc
}
You can also do this by constructing an N-dimensional key class to use as the map key. It would need the appropriate equals() and hashCode() methods defined and would probably be a cleaner solution but the above will work.
Obviously if you were going to store every value of a 100x100 array in the sparse array class there would be an overhead (as all maps have overheads). This brings in the dense array. The sparse array only stores values where values are set. The dense array stores a value for every possible key (within the specified range).
Also the dense array is similar to the fixed array but not quite the same. Fixed arrays are hard to extend once created (well, it's an expensive operation so it's generally not allowed) whereas dense arrays might be built to be extended, like you could use them for a spreadsheet and extend the max X and Y values are the user uses more and more cells so you define a rectangle encompassing all used values.
If you're looking to do a spreadsheet-type application (deduced, possibly wrongly, from the spring-framework tag and the B-1/C-2 names), sparse arrays are probably the way to go.
Colt has one such implementation.
I answered a similar question here.
I am assuming you need a data structure in Java to store these values.
You could define a 2D array in Java using the following syntax.
String[][] strArr = new String[5][5]; //defines a 5*5 String array
String[][] strArr2 = new String[1][2]; //defines a 1*2 String array
Please note that the arrays can hold values of only 1 datatype. The specific items can be dereferenced using something like
System.out.println(strArr2[0][1]);
For your specific example, you could also use java.util.Map class and store the data as key-value pairs but this requires the "keys" to be unique. e.g.,
Map<String,Integer> keyval = new HashMap<String, Integer>();
keyval.put("B",1);
keyval.put("C",2);
keyval.put("D",3);
keyval.put("D",4); //wrong. will overwrite the previous entry.
I guess what you need is a Map of ArrayLists:
HashMap<String, ArrayList<YourClass>> map;
This way B-1 would be map.get("B").get(1);
I'm writing a program to calculate a value that is a measure of the similarity between two objects. The comparison is commutative, so compare(a, b) == compare(b, a).
The program's output to the console is a matrix of all results. However, since the matrix has each comparison twice ((a, b) and (b, a)), I'd like to save time by only calculating it once. What is the best way to cache these results?
Rough example of what the output looks like:
a b c
a 0 20 9001
b 20 0 333
c 9001 333 0
It sounds like you're already caching the results really - in the matrix. Just compute one "triangle" of the matrix and fill in the rest from that:
// Compute one triangle
for (int i=0; i < size; i++)
{
for (int j=0; j <= i; j++)
{
matrix[i][j] = computeValue(i, j);
}
}
// Now mirror it
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
matrix[i][j] = matrix[j][i];
}
}
As others have mentioned, you should just calculate one side of the triangle. You don't hove to copy it or even allocate space for it either. Just transform your x and y coordinates into a single index, and you can have an array that's a little over half the size of the full square matrix. eg:
class SymmetricMatrix {
private final double[];
/**
* #param size the size of one dimension of the matrix. eg: 3 for a 3x3 matrix.
*/
SymmetricMatrix(int size) {
matrix = new double[index(size) + 1];
}
private index(int x, int y) {
if (x > y) {
int tmp = x;
x = y;
y = tmp;
}
// now x <= y
i = (y * y + y) / 2 + x;
}
public double get(int x, int y) {
return matrix[index(x, y)];
}
public void set(int x, int y, double value) {
matrix[index(x, y)] = value;
}
}
This example uses double values, but you can easily adjust that (or even make it generic, if you want to use objects).
To fill it in:
SymmetricMatrix matrix = new SymmetricMatrix(size);
for (int y = 0; y < size; y++) {
for (int x = 0; x <= y; x++) {
matrix.set(x, y, /* value */);
}
}
Calculate only one triangle, and make an access function like
get(int x, int y) {
if (x > y) { return matrix[x][y] };
return matrix[y][x];
Looks like you don't need it for this task but if you have an expensive function and need to cache the result there is a very good thread safe method here:
http://www.javaspecialists.eu/archive/Issue125.html
You need to be rather careful with caching results of methods like compareTo and equals.
If you have N array instances you potentially need to cache N^2 comparison results. (This is of course application dependent ...)
Also, if your application creates and discards large numbers of (matrix) instances, then you may end up with lots of entries in the cache, resulting in garbage retention problems. You can mitigate this with weak references, but they make garbage collection significantly slower.
If I was doing this, I'd first profile the application to determine if the compareTo and equals methods are really bottlenecks. Then if they were, I'd consider using something other than caching to speed up the methods; e.g. storing a lazily computed hash with each array could speed up equals.