0

I have a class Test with attributes

--> Integer id1
--> Integer id2
--> String stringValue.

So there are list of stringValues per (id1 and id2) combination of unique ids. I want to be able store that in a collection. Example:

  test1 : id1 = 1, id2 = 2 , stringValue = one
  test11 : id1 = 1, id2 = 2 , stringValues =two
  test111 : id1 = 1, id2 = 3 , stringValues =three
  test2 : id1 = 5, id2 = 3, stringValues = four
  test22: id1 = 5, id2 = 2, stringValues = five
  test222: id = 5, id2 = 3, stringValues = six

Desired end result is store the objects as

-> {id = 1, id = 2, String = {one, two} } 
-> {id = 1 , id =3 , String = {three}}
-> {id = 5, id = 3 , String = {four,six}}
-> {id = 5, id = 2 , String = {five}}

I want to be able to store the list of 'test' objects in a collection. I tried Set<> , overriding the equals and hashcode but it didnt work as expected. Here you go

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id1 == null) ? 0 : id1.hashCode());
        result = prime * result + ((id2 == null) ? 0 : id2.hashCode());
        return result;
    }


        @Override
    public boolean equals(Object obj) {
        if( obj instanceof Test){
            Test test = (Test) obj;
            return (test.id1 == this.id1 && test.id2 == this.id2);
        } else {
            return false;
        }
    }

I loop through each object and store it in a SET. it does eliminate (redundant combination of [id1 and id2], but it also eliminates the respective string value.) Oops I forgot to mention I get the data from a resultset retrieved from database. so each row consists of id1, id2 and a string value(which is different for all rows). some rows will have a common id1 and id2 values

Can someone please suggest me with any pointers please ?

Thank you in advance

user2988851
  • 157
  • 2
  • 13
  • 'Didn't work as expected' is not something anyone can help you with unless you specifically describe what you tried, how it behaved and how that's different from what you expected. Include code. – pvg Mar 30 '17 at 18:27
  • Please post the stacktrace if any error is encountered as i feel your approach is correct just there might be problem with the implementation – Rahul Singh Mar 30 '17 at 18:28
  • ok let me post the code – user2988851 Mar 30 '17 at 18:28
  • "I tried Set<> , overriding the equals and hashcode but it didnt work as expected." - may you post the code, please. Because I'm sure it must work. I've done exactly the same last week and this approach works for sure :) – Mikhail Antonov Mar 30 '17 at 18:28
  • Edit your question with the additional details. – pvg Mar 30 '17 at 18:29
  • @MikhailAntonov : I added the info. let me know if you have any questions – user2988851 Mar 30 '17 at 18:36
  • 2
    use .equals not == to compare strings. And write yourself a 3 line test case to test your .equals and hashCode actually work. – pvg Mar 30 '17 at 18:36
  • "didnt work as expected": what did you expect? – Henry Mar 30 '17 at 18:38
  • yep, it seems like there should be equals used instead of == – Mikhail Antonov Mar 30 '17 at 18:40
  • I have a precise list of objects as example now. the objects should be stored with eliminating the redundant combination of id1 and id2. Also the list of objects are not necessarily sorted as per ids. – user2988851 Mar 30 '17 at 18:41
  • The list of objects doesn't matter, what matters is your implementation of `equals` is buggy. You are comparing strings for object identity, not equality. – pvg Mar 30 '17 at 18:42
  • Also check if either one of the ids is null – fps Mar 30 '17 at 18:44
  • What's the type of the `id1` and `id2` fields? – Henry Mar 30 '17 at 18:47
  • @pvg: correct me, so I cant use '==' even if the ids are integers ? – user2988851 Mar 30 '17 at 18:48
  • @Henry : Integer – user2988851 Mar 30 '17 at 18:48
  • You can use == for ints yes. Why don't you actually post your class or at least a [MCVE] version of it? – pvg Mar 30 '17 at 18:49
  • If the type is `Integer` you must use equals as well. There are some cases with small numbers where `==` will sometimes work to compare the values but you cannot be sure. – Henry Mar 30 '17 at 18:51
  • Oh you have Integer not ints right? see http://stackoverflow.com/questions/12547201/comparing-integer-objects – pvg Mar 30 '17 at 18:51
  • @user2988851 you can use == for Integers, but it has a different meaning. For an integer == returns true if both operands are the *same* object, not if they both hold same numeric value. equals compares contents – Mikhail Antonov Mar 30 '17 at 18:51
  • 2
    And again, all of this theory is unnecessary if you'd simply write a test case to see if your methods do what you think they do. It seems like you wrote an equals and a hashcode, threw stuff into a Hashset and then were surprised the result was 'unexpected'. Test your code, it's much slower to have a bunch of strangers on the internet do it for you, sight unseen. – pvg Mar 30 '17 at 18:53
  • @MikhailAntonov : I loop through each object and store it in a SET. it does eliminate (redundant combination of [id1 and id2], but it also eliminates the respective string value.) . Also I will keep a note to change == to equals – user2988851 Mar 30 '17 at 19:01
  • OMG I kind of fail to understand you given the last edit. So you say: "but it also eliminates the respective string value"... Of course it does! If you use (id1 + id2) unique key, then everything with same combination will be eliminated. If it shouldn't, then just use a `List` collection and do not override `equals` and `hashCode` methods. Moreover, if this is a resultset, then there's more logic to do all your "unification", sorting and filtering in db request, rather then doing it manually while handling the result. This is kind of confusing. – Mikhail Antonov Mar 30 '17 at 19:10
  • @MikhailAntonov : I would use that data to loop else where using the combination of the ids and store the string values. – user2988851 Mar 30 '17 at 19:27
  • Maybe you should edit your question to describe in detail what it is you're attempting to accomplish. – pvg Mar 30 '17 at 19:31
  • @pvg : added lil more info – user2988851 Mar 30 '17 at 19:38

1 Answers1

1

Does that solve your problem?

import java.util.*;

public class Playground1 {
    public static void main(String[] args) {

        // fake resultset
        List<DBResultSetRowEmulation> resultSetEmulation = new ArrayList<>();
        resultSetEmulation.add(new DBResultSetRowEmulation(1, 2, "one"));
        resultSetEmulation.add(new DBResultSetRowEmulation(1, 2, "two"));
        resultSetEmulation.add(new DBResultSetRowEmulation(1, 3, "three"));
        resultSetEmulation.add(new DBResultSetRowEmulation(5, 3, "four"));
        resultSetEmulation.add(new DBResultSetRowEmulation(5, 2, "five"));
        resultSetEmulation.add(new DBResultSetRowEmulation(5, 3, "six"));

        Map<DoubleIndex, List<String>> resultData = new HashMap<>();

        // iterate through resultset
        for(DBResultSetRowEmulation row: resultSetEmulation) {
            DoubleIndex curRecordIdx = new DoubleIndex(row.a, row.b);
            if (resultData.containsKey(curRecordIdx)) {
                // append current string to some existing id1+id2 combination
                resultData.get(curRecordIdx).add(row.c);
            } else {
                // create a new list for new id1+id2 combination
                resultData.put(curRecordIdx, new ArrayList<>(Collections.singletonList(row.c)));
            }
        }

        System.out.println(resultData);
    }

    private static class DBResultSetRowEmulation {
        Integer a, b;
        String c;

        DBResultSetRowEmulation(Integer a, Integer b, String c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }

    private static class DoubleIndex {
        private Integer a,b;

        public DoubleIndex(Integer a, Integer 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;

            DoubleIndex that = (DoubleIndex) o;

            return a.equals(that.a) && b.equals(that.b);
        }

        @Override
        public int hashCode() {
            int result = a.hashCode();
            result = 31 * result + b.hashCode();
            return result;
        }

        @Override
        public String toString() {
            return "id{" +
                    "a=" + a +
                    ", b=" + b +
                    '}';
        }
    }
}

output:

{id{a=1, b=2}=[one, two],

id{a=1, b=3}=[three],

id{a=5, b=2}=[five],

id{a=5, b=3}=[four, six]}

You will have to figure out how to sort that result by yourself.

Community
  • 1
  • 1
Mikhail Antonov
  • 1,297
  • 3
  • 21
  • 29