Skip to content

Conversation

@jiminhsieh
Copy link
Contributor

Fix #739

@jiminhsieh
Copy link
Contributor Author

Signed-off-by: Jimin Hsieh jimin.hsieh.engineer@gmail.com

Copy link
Contributor

@donraab donraab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend naming the factory methods, withOccurrences instead of ofWithOccurrences. I was also thinking it would be nice to add withOccurrences/withoutOccurrences to MutableBag and newWithOccurrences/newWithoutOccurrences to ImmutableBag.


<T> ImmutableBag<T> ofWithOccurrences(T element, int occurrence);

<T> ImmutableBag<T> ofWithOccurrences(T element1, int occurrence1, T element2, int occurrence2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect to see withOccurrences or ofOccurrences or both to be consistent with naming.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have withOccurrences and ofOccurrences since we have of and with those 2 APIs. In this situation, the users will be much easier to find the new APIs.

@jiminhsieh
Copy link
Contributor Author

it would be nice to add withOccurrences/withoutOccurrences to MutableBag and newWithOccurrences/newWithoutOccurrences to ImmutableBag.

I can understand the behavior of withOccurrences and newWithOccurrences, but I don't know the expected behavior or APIs for withoutOccurrences and newWithoutOccurrences. @donraab Could you explain more about those APIs with withoutOccurrences? Thanks.

I am thinking should I implement the withOccurrences for mutable bag factories? I already implement those APIs for the immutable bag factories, it's probably better to implement for mutable too.

@donraab
Copy link
Contributor

donraab commented Sep 30, 2019

@jiminhsieh This is what I am thinking for the implementation on MutableBag.

default MutableBag<T> withOccurrences(T element, int occurrences)
{
    this.addOccurrences(element, occurrences);
    return this;
}

default MutableBag<T> withoutOccurrences(T element, int occurrences)
{
    this.removeOccurrences(element, occurrences);
    return this;
}

Does this make sense?

Some useful blog references:

1. Preposition Preference

2. The Occurrences of Occurrences

@donraab
Copy link
Contributor

donraab commented Oct 6, 2019

@jiminhsieh the withOccurrences and withoutOccurrences methods on MutableBag could either added in a separate PR, or could be used to implement withOccurrences and ofOccurences on the factories. I'll leave it up to you. I agree with you that to be consistent we should have both withOccurrences and ofOccurrences on the factory classes.

@donraab donraab changed the title Add new APIs, ofWithOccurrences, to bag immutable factories Add new APIs, ofOccurrences and withOccurrences, to bag immutable factories Oct 6, 2019
@donraab donraab changed the title Add new APIs, ofOccurrences and withOccurrences, to bag immutable factories Add new APIs, ofOccurrences and withOccurrences, to bag mutable and immutable factories Oct 6, 2019
@jiminhsieh
Copy link
Contributor Author

I will implement this PR with withOccurrences and ofOccurrences to mutable and immutable factories.

I was also thinking it would be nice to add withOccurrences/withoutOccurrences to MutableBag and newWithOccurrences/newWithoutOccurrences to ImmutableBag.

I think this should be another PR since this includes a new API, withoutOccurrences, and I need to implement for MutableBag and ImmutableBag instead of ImmutableBagFactory and MutableBagFactory which I will change this time.

@jiminhsieh
Copy link
Contributor Author

@donraab I'm thinking about rewriting history to fewer commits since I will be much easier for you to review. Is that ok with you?

@nikhilnanivadekar
Copy link
Contributor

I would prefer if you could squash all the commits to a single commit per feature. Thanks again for your contribution!

@donraab
Copy link
Contributor

donraab commented Oct 9, 2019

@donraab I'm thinking about rewriting history to fewer commits since I will be much easier for you to review. Is that ok with you?

Yes, please squash all the commits.


<T> ImmutableBag<T> withOccurrences(ObjectIntPair<T>... elementsWithOccurrences);

ImmutableBag<Integer> withOccurrences(IntIntPair... elementsWithOccurrences);
Copy link
Contributor

@donraab donraab Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jiminhsieh, I do not understand why withOccurrences(IntIntPair... elementsWithOccurrences) is necessary here. If there is a use case for this, I would rather add the factory methods to the primitive Bag factories, so this returns an ImmutableIntBag.

I understand why you might want to replace this with ObjectIntPair here to return an ImmutableBag<T>, but IntIntPair returning a boxed ImmutableBag<Integer> doesn't make sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withOccurrences(IntIntPair... elementsWithOccurrences)

The reason I provided this API is I already provided the following API:

withOccurrences(ObjectIntPair<T>... elementsWithOccurrences);

Above API will need to use:

PrimitiveTuples.pair("2", 2)

Which will return ObjectIntPair.
If I use this:

PrimitiveTuples.pair(2, 2)

Which will return IntIntPair.
That's why I have withOccurrences(IntIntPair... elementsWithOccurrences);

IntIntPair returning a boxed ImmutableBag doesn't make sense to me.

If the APIs with varargs make sense to you, I could see the possibility of returning ImmutableIntBag instead of the current one. If there is a better collection than ImmutableIntBag, please let me know too. Thanks.

Copy link
Contributor

@donraab donraab Nov 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method would make more sense on IntBags in the MutableIntBagFactory and ImmutableIntBagFactory interfaces and implementations.

For Example:

IntBag bag = IntBags.mutable.withOccurrences(
    PrimitiveTuples.pair(1, 10), 
    PrimitiveTuples.pair(2, 20));

There is also ShortBag, ByteBag, CharBag, FloatBag, LongBag, DoubleBag, BooleanBag. They should have the equivalent methods. But I would recommend doing this in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any update on this @jiminhsieh?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@donraab I don't have any update yet, I was busy at the end of last year. However, this PR will be the first finished PR for 2020. :)


<T> MutableBag<T> withOccurrences(ObjectIntPair<T>... elementsWithOccurrences);

MutableBag<Integer> withOccurrences(IntIntPair... elementsWithOccurrences);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@donraab
Copy link
Contributor

donraab commented Jan 3, 2020

Hi @jiminhsieh please squash the commits again. Thanks!


<T> MutableBag<T> with(T... elements);

<T> MutableBag<T> withOccurrences(T element, int occurrence);
Copy link
Contributor

@donraab donraab Jan 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a choice to make here. The specification and implementation of this method looks fine, but will require the next version of Eclipse Collections to be 11.0 because the withOccurrences methods do not have default implementations. As long as @nikhilnanivadekar is ok with this, then I am fine. I would suggest adding @since 11.0 tags to the interfaces for MutableBagFactory and ImmutableBagFactory then as this will require a major release and will be nice to see when they were added.

Copy link
Contributor

@donraab donraab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jiminhsieh please add @since 11.0 to the new methods on the MutableBagFactory and ImmutableBagFactory interfaces.

After you add the tags, please rebase and then I will approve and merge the changes. Thanks!

Copy link
Contributor

@motlin motlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if our next version is a major release (11.0) I still think this change should be made using default methods in the interfaces. I think it's easier than not doing it.

@Override
public <T> ImmutableBag<T> withOccurrences(T element1, int occurrence1, T element2, int occurrence2, T element3, int occurrence3, T element4, int occurrence4)
{
MutableBag<T> bag = new HashBag<>(occurrence1 + occurrence2 + occurrence3 + occurrence4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pre-sizings are wrong. This map will have four elements, and could be pre-sized to 4, or not pre-sized. This implementation could easily lead to OutOfMemoryError and must be fixed.

My recommendation would be not to pre-size at all, nor call a constructor. You could replace this with a call to empty(), and then the implementation could be pulled up as a default method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching that. I will fix this soon.

@Override
public <T> ImmutableBag<T> withOccurrences(ObjectIntPair<T>... elementsWithOccurrences)
{
MutableBag<T> bag = new HashBag<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only location where pre-sizing may have a benefit. The size would be the array length.

public void topOccurrences()
{
MutableBagIterable<String> strings = this.newWithOccurrences(
MutableBagIterable<String> strings = Bags.mutable.withOccurrences(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add at least one test where the number of occurrences is Integer.MAX_VALUE. This should fail with OutOfMemoryError until the pre-sizing fix is in place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to change the last element of occurrences to Integer.MAX_VALUE. I didn't meet OutOfMemoryError even I didn't fix pre-sizing.
Here is the change:

MutableBagIterable<String> strings = Bags.mutable.withOccurrences(
                PrimitiveTuples.pair("one", 1),
                PrimitiveTuples.pair("two", 2),
                PrimitiveTuples.pair("three", 3),
                PrimitiveTuples.pair("four", 4),
                PrimitiveTuples.pair("five", 5),
                PrimitiveTuples.pair("six", 6),
                PrimitiveTuples.pair("seven", 7),
                PrimitiveTuples.pair("eight", 8),
                PrimitiveTuples.pair("nine", 9),
                PrimitiveTuples.pair("ten", Integer.MAX_VALUE));

Should I still add one test for this?

But I do understand that the reason of pre-sizing for the variable arguments. The underlying storage could grow dynamically and exceed than we need. So it will be better to pre-sizing in the initialization.

@donraab
Copy link
Contributor

donraab commented Jan 10, 2020

Even if our next version is a major release (11.0) I still think this change should be made using default methods in the interfaces. I think it's easier than not doing it.

@jiminhsieh I agree with Craig's idea here. This change can be made via default methods. @nikhilnanivadekar Thoughts?

@jiminhsieh
Copy link
Contributor Author

this change should be made using default methods in the interfaces

Sorry, I can't catch up on this one. Could someone elaborate this more to me? Thanks. :)

@nikhilnanivadekar
Copy link
Contributor

@motlin can you please help @jiminhsieh with your review comments, please?

@motlin
Copy link
Contributor

motlin commented Feb 15, 2020

I made most of the changes I wanted to see in these commits:

  • 2e5d3ce Fix pre-sizing in MutableBagFactoryImpl.
  • a692313 Fix pre-sizing and simplify ImmutableBagFactoryImpl.
  • 2f0649e Pull methods up from MutableBagFactoryImpl to MutableBagFactory as default methods.
  • 4db0ef8 Pull methods up from ImmutableBagFactoryImpl to ImmutableBagFactory as default methods.

Feel free to cherry-pick these or squash them in. I also think this could use a few additional tests to get full coverage.

@motlin
Copy link
Contributor

motlin commented Feb 15, 2020

Also, I completely removed pre-sizing. If we add a method like empty(size) or something like that, we can add pre-sizing back in.

@jiminhsieh jiminhsieh changed the title Add new APIs, ofOccurrences and withOccurrences, to bag mutable and immutable factories [WIP] Add new APIs, ofOccurrences and withOccurrences, to bag mutable and immutable factories Feb 17, 2020
@jiminhsieh
Copy link
Contributor Author

Current code coverage of those 2 classes:

Screen Shot 2020-02-22 at 18 28 25

@jiminhsieh jiminhsieh changed the title [WIP] Add new APIs, ofOccurrences and withOccurrences, to bag mutable and immutable factories Add new APIs, ofOccurrences and withOccurrences, to bag mutable and immutable factories Feb 22, 2020
@nikhilnanivadekar
Copy link
Contributor

@motlin can you please review this PR since you have been working on it. Also, I see multiple commits on this one, is that the plan or we want these commits to be squashed?

@jiminhsieh
Copy link
Contributor Author

@nikhilnanivadekar I can squash into one commit. But I have a question for @motlin. Is it fine for you that I use co-author since you do help me with those commits. Thanks.

Copy link
Contributor

@motlin motlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should squash all the commits into one. If you know how to use co-authors in git, then yes that would be great. Otherwise, it's no big deal to have yourself as the sole author. Once it's squashed/rebased I think this is good to merge in.

@jiminhsieh jiminhsieh force-pushed the add-new-apis branch 3 times, most recently from 7a3e873 to 6fff029 Compare February 24, 2020 09:54
@motlin
Copy link
Contributor

motlin commented Feb 25, 2020

LGTM. Would you also rebase it on top of upstream/master?

…nd immutable factories

Co-authored-by: Jimin Hsieh <jimin.hsieh.engineer@gmail.com>
Co-authored-by: Craig P. Motlin <cmotlin@gmail.com>
Signed-off-by: Jimin Hsieh <jimin.hsieh.engineer@gmail.com>
@jiminhsieh
Copy link
Contributor Author

Rebased on the master without any conflict.

@motlin motlin merged commit a4e2c6c into eclipse-collections:master Feb 25, 2020
@motlin
Copy link
Contributor

motlin commented Feb 25, 2020

Thank you for the contribution!

@jiminhsieh jiminhsieh deleted the add-new-apis branch March 3, 2020 00:42
@Isammoc
Copy link

Isammoc commented Apr 29, 2020

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bag factories with occurrences

5 participants