-1

I have an array of 24 colors. Occasionally when I generate it I get colors that have the exact same RGB values. What I want to do is find the duplicates in the array and change the value of the match by like 1 or 2. Just so that it doesn't match anymore.

Here is my array of colors. Notice that there are 3 of the exact shade of red. I want each one to be slightly different from each other. Keep the R channel the same but change the G and or B channels to be like 1 or 2 numbers higher.

Color Array: [java.awt.Color[r=255,g=194,b=23], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=0,g=67,b=255], java.awt.Color[r=0,g=255,b=175], java.awt.Color[r=255,g=13,b=10], java.awt.Color[r=255,g=115,b=43], java.awt.Color[r=2,g=92,b=255], java.awt.Color[r=241,g=219,b=255], java.awt.Color[r=255,g=194,b=0], java.awt.Color[r=231,g=210,b=255], java.awt.Color[r=0,g=43,b=255], java.awt.Color[r=255,g=80,b=0], java.awt.Color[r=255,g=205,b=27], java.awt.Color[r=255,g=0,b=9], java.awt.Color[r=205,g=199,b=255], java.awt.Color[r=0,g=44,b=255], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=21,g=255,b=219], java.awt.Color[r=255,g=199,b=51], java.awt.Color[r=255,g=82,b=2], java.awt.Color[r=215,g=198,b=255], java.awt.Color[r=0,g=255,b=203], java.awt.Color[r=255,g=98,b=28]]

What I was thinking was iterating through the array.

for(int i = 0; i < colorArray.length; i++){
    if(colorArray[i] == //not sure what this would be equal to as it will be checking all the values in the array ) {
       colorArray[i].getBlue() =  matchingColor.getBlue() += 1;
       colorArray[i].getGreen()  matchingColor.getGreen() += 2; //These are example values just to make sure that they have no match
    }
}
cuber
  • 371
  • 5
  • 20
  • 3
    Any particular reason you can't use [`colorArray[i].equals(matchingColor)`](https://docs.oracle.com/javase/7/docs/api/java/awt/Color.html#equals(java.lang.Object))? – Tibrogargan Apr 24 '17 at 02:05
  • for my comparisons comparing the reference instead of the object seems to be working better. I am not opposed to it but would rather just compare the reference. @Tibrogargan – cuber Apr 24 '17 at 02:08
  • 1
    Why don't you generate them into some kind of `Set`, and stop when the `Set` has the right number of elements? – Dawood ibn Kareem Apr 24 '17 at 02:08
  • Also, it's possible to have two different `Color` objects with the same RGB values, so comparing the reference is no good. – Dawood ibn Kareem Apr 24 '17 at 02:09
  • 1
    `equals` does not do reference comparison, it is object implementation dependent. In this case: **The result is true if and only if the argument is not null and is a Color object that has the same red, green, blue, and alpha values as this object.** – Tibrogargan Apr 24 '17 at 02:09
  • I don't want to remove the duplicates. I just want to find a match in the array and just change it slightly. @DawoodibnKareem – cuber Apr 24 '17 at 02:09
  • when you have found the Color using `equals` then replace the Object with the new Color Object – Scary Wombat Apr 24 '17 at 02:11
  • I can compare the actual object I just wasn't doing so at the time. @Tibrogargan I know that `equals` compares content and the `==` compares the reference. i stated I wasn't doing so at the time because I didn't run into it being a problem and I am not opposed to changing it. – cuber Apr 24 '17 at 02:12

2 Answers2

4

Learning the APIs of the Classes you use is really helpful.

for(int i = 0; i < colorArray.length; i++) {
    // use while in case the color is black/white.  (May thrash for few iterations)
    while (colorArray[i].equals(matchingColor)) {
       colorArray[i] = (Math.random() < 0.5)?colorArray[i].brighter():colorArray[i].darker();
    }
}
Tibrogargan
  • 4,508
  • 3
  • 19
  • 38
  • How do I check if colorArray[i].equals another color in the array? – cuber Apr 24 '17 at 02:16
  • To check for duplicates you're better off using a data type to store your elements that supports this sort of functionality. A primitive array isn't terribly useful for this - you have to search the entire thing manually. A set may be useful (as @DawoodibnKareem suggests) – Tibrogargan Apr 24 '17 at 02:19
  • Look at [this](http://stackoverflow.com/questions/13138990/how-to-search-in-a-list-of-java-object) first – Tibrogargan Apr 24 '17 at 02:22
  • I don't believe this will work in all cases. When you modify `colorArray[i]`, you could be setting it to the same colour as something else in the array. I'm assuming this is intended to sit inside a second loop, where `matchingColor` iterates through the colours in the array - so it's no good if `colorArray[i]` gets changed to a value that has _already been_ `matchingColor` on some iteration. – Dawood ibn Kareem Apr 24 '17 at 04:49
  • Nor does it work if you have a lot of the same color, since it could potentially end up in an endless loop. Just using `brigher`/`darker` is an easy fix, but it's a step towards a good solution that covers all the edge cases. Need to take care not to over-engineer. – Tibrogargan Apr 24 '17 at 04:53
0

Here is a solution using a Set to maintain uniqueness. This saves re-inventing all the functionality to check for duplicates. It takes advantage of the fact that the add method of the Set interface returns true if the object has been added to the set. Under the covers, of course, it uses the equals method of Color.

In the event that a duplicate is found, we repeatedly try modifying the Color a little, by doing a bitwise exclusive-or of its three components, until we come to a unique one.

public void deduplicate(Color[] colors) {
    Set<Color> uniqueColors = new HashSet<>();
    for (int which = 0; which < colors.length; which++) {
        Color originalColor = colors[which];
        boolean unique = uniqueColors.add(originalColor);
        for (int modifyBy = 1; !unique ; modifyBy++) {
            colors[which] = new Color(
                    originalColor.getRed() ^ modifyBy, 
                    originalColor.getGreen() ^ modifyBy, 
                    originalColor.getBlue() ^ modifyBy);
            unique = uniqueColors.add(colors[which]);
        }
    }
}
Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110