Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #37708 > unrolled thread

Can I put a filter into a lambda?

Started byEric Douglas <e.d.programmer@gmail.com>
First post2017-12-01 12:52 -0800
Last post2017-12-08 15:00 +0100
Articles 8 — 3 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Can I put a filter into a lambda? Eric Douglas <e.d.programmer@gmail.com> - 2017-12-01 12:52 -0800
    Re: Can I put a filter into a lambda? Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-12-01 16:28 -0500
      Re: Can I put a filter into a lambda? Eric Douglas <e.d.programmer@gmail.com> - 2017-12-04 05:03 -0800
        Re: Can I put a filter into a lambda? Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-12-04 08:20 -0500
          Re: Can I put a filter into a lambda? Eric Douglas <e.d.programmer@gmail.com> - 2017-12-04 05:32 -0800
            Re: Can I put a filter into a lambda? Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-12-04 09:29 -0500
              Re: Can I put a filter into a lambda? Eric Douglas <e.d.programmer@gmail.com> - 2017-12-04 07:14 -0800
              Re: Can I put a filter into a lambda? Sebastian <nowhere@nirvana.org> - 2017-12-08 15:00 +0100

#37708 — Can I put a filter into a lambda?

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-12-01 12:52 -0800
SubjectCan I put a filter into a lambda?
Message-ID<321ee28f-bbea-4565-a48e-c0476d9a78d4@googlegroups.com>
I haven't gotten around to mastering the lambda syntax.
I have a JTable with a custom row sorter building an index of all model rows:

rowToModelIndex.clear();
if (modelRowCount > 0) {
     if (getRowFilter() != null) {
          for (int r = 0; r < modelRowCount; r++) {
               if (include(r)) {
                    rowToModelIndex.add(r);
               }
          }
     } else {
          rowToModelIndex.addAll(Stream.iterate(firstRow, n -> n + 1).limit(modelRowCount).collect(Collectors.toList()));
     }
}

If it's a straight up series it's a lambda.  Can the filter loop be also?  I would guess that would be more efficient.

[toc] | [next] | [standalone]


#37709

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2017-12-01 16:28 -0500
Message-ID<ovshh6$8q1$1@dont-email.me>
In reply to#37708
On 12/1/2017 3:52 PM, Eric Douglas wrote:
> I haven't gotten around to mastering the lambda syntax.
> I have a JTable with a custom row sorter building an index of all model rows:
> 
> rowToModelIndex.clear();
> if (modelRowCount > 0) {
>       if (getRowFilter() != null) {
>            for (int r = 0; r < modelRowCount; r++) {
>                 if (include(r)) {
>                      rowToModelIndex.add(r);
>                 }
>            }
>       } else {
>            rowToModelIndex.addAll(Stream.iterate(firstRow, n -> n + 1).limit(modelRowCount).collect(Collectors.toList()));
>       }
> }
> 
> If it's a straight up series it's a lambda.  Can the filter loop be also?  I would guess that would be more efficient.

     It's not clear what your filter loop is actually doing:
the RowFilter seems never to be used, and I can't find any
one-argument include() method in any Java SE (8 or 9) class.
(You also haven't shown what rowToModelIndex is, but I'll
guess it's a Collection<Integer>, possibly List<Integer>).
So I'll restate the problem without the table trappings:

     1) If getRowFilter() returns null, you want a List of
        all the values 0 through modelRowCount-1, in order.

     2) If getRowFilter() returns non-null, you want a List
        of the same values, excluding those for which the
        boolean-valued include(int) method returns false.

     If that's not the goal, read no further.  But if it is
(or is close enough for jazz), both cases can be written
more simply:

	// Case 1:
	rowModelIndex = IntStream.range(0, modelRowCount)
	    .mapToObj(Integer::valueOf)
	    .collect(Collectors.toList());

	// Case 2:
	rowModelIndex = IntStream.range(0, modelRowCount)
	    .filter((value) -> include(value))
	    .mapToObj(Integer::valueOf)
	    .collect(Collectors.toList());

     Final point: If you can't stop worrying about efficiency,
at the very least stop *guessing* about it!

-- 
esosman@comcast-dot-net.invalid
Eleven hundred forty-six days to go.

[toc] | [prev] | [next] | [standalone]


#37712

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-12-04 05:03 -0800
Message-ID<a7f8b0f0-79cb-4f83-bf77-2ce7d94a2a19@googlegroups.com>
In reply to#37709
On Friday, December 1, 2017 at 4:28:26 PM UTC-5, Eric Sosman wrote:
>      It's not clear what your filter loop is actually doing:
> the RowFilter seems never to be used, and I can't find any
> one-argument include() method in any Java SE (8 or 9) class.
> (You also haven't shown what rowToModelIndex is, but I'll
> guess it's a Collection<Integer>, possibly List<Integer>).
> So I'll restate the problem without the table trappings:
> 
>      1) If getRowFilter() returns null, you want a List of
>         all the values 0 through modelRowCount-1, in order.
> 
>      2) If getRowFilter() returns non-null, you want a List
>         of the same values, excluding those for which the
>         boolean-valued include(int) method returns false.
> 
>      If that's not the goal, read no further.  But if it is
> (or is close enough for jazz), both cases can be written
> more simply:
> 
> 	// Case 1:
> 	rowModelIndex = IntStream.range(0, modelRowCount)
> 	    .mapToObj(Integer::valueOf)
> 	    .collect(Collectors.toList());
> 
> 	// Case 2:
> 	rowModelIndex = IntStream.range(0, modelRowCount)
> 	    .filter((value) -> include(value))
> 	    .mapToObj(Integer::valueOf)
> 	    .collect(Collectors.toList());
> 
>      Final point: If you can't stop worrying about efficiency,
> at the very least stop *guessing* about it!
> 
rowToModelIndex is an ArrayList<Integer>.

Yes the include method says if the row filter is null then include every row number, if not null then include rows based on the boolean value from the row filter include method.

Milliseconds do count in a row filtering method which executes thousands of times.

[toc] | [prev] | [next] | [standalone]


#37713

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2017-12-04 08:20 -0500
Message-ID<p03i39$n76$1@dont-email.me>
In reply to#37712
On 12/4/2017 8:03 AM, Eric Douglas wrote:
> On Friday, December 1, 2017 at 4:28:26 PM UTC-5, Eric Sosman wrote:
>>       It's not clear what your filter loop is actually doing:
>> the RowFilter seems never to be used, and I can't find any
>> one-argument include() method in any Java SE (8 or 9) class.
>> (You also haven't shown what rowToModelIndex is, but I'll
>> guess it's a Collection<Integer>, possibly List<Integer>).
>> So I'll restate the problem without the table trappings:
>>
>>       1) If getRowFilter() returns null, you want a List of
>>          all the values 0 through modelRowCount-1, in order.
>>
>>       2) If getRowFilter() returns non-null, you want a List
>>          of the same values, excluding those for which the
>>          boolean-valued include(int) method returns false.
>>
>>       If that's not the goal, read no further.  But if it is
>> (or is close enough for jazz), both cases can be written
>> more simply:
>>
>> 	// Case 1:
>> 	rowModelIndex = IntStream.range(0, modelRowCount)
>> 	    .mapToObj(Integer::valueOf)
>> 	    .collect(Collectors.toList());
>>
>> 	// Case 2:
>> 	rowModelIndex = IntStream.range(0, modelRowCount)
>> 	    .filter((value) -> include(value))
>> 	    .mapToObj(Integer::valueOf)
>> 	    .collect(Collectors.toList());
>>
>>       Final point: If you can't stop worrying about efficiency,
>> at the very least stop *guessing* about it!
>>
> rowToModelIndex is an ArrayList<Integer>.

     If it *must* be an ArrayList (and not some other kind of List),
you might want to change the last bit to

	.collect(Collectors.toCollection(ArrayList::new));

Although the toList() method appears to use ArrayList anyhow, it
doesn't guarantee to do so -- meaning that it might use some other
List in a future Java, or in circumstances I haven't studies (e.g.,
it might behave differently with a parallel stream).

> Milliseconds do count in a row filtering method which executes thousands of times.

     If performance is important, measure.  Don't guess.

-- 
esosman@comcast-dot-net.invalid
Eleven hundred forty-three days to go.

[toc] | [prev] | [next] | [standalone]


#37714

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-12-04 05:32 -0800
Message-ID<9545f24b-39da-4eab-8c65-365a299b3b2a@googlegroups.com>
In reply to#37713
On Monday, December 4, 2017 at 8:20:59 AM UTC-5, Eric Sosman wrote:
>      If it *must* be an ArrayList (and not some other kind of List),
> you might want to change the last bit to
> 
> 	.collect(Collectors.toCollection(ArrayList::new));
> 
> Although the toList() method appears to use ArrayList anyhow, it
> doesn't guarantee to do so -- meaning that it might use some other
> List in a future Java, or in circumstances I haven't studies (e.g.,
> it might behave differently with a parallel stream).
> 
ok, thanks, I'll keep that in mind.  I'll have to test if the variable can be assigned and if that would be more efficient.  Currently it doesn't matter what kind of list because I made the rowToModelIndex variable final, just calling clear() then addAll().

> > Milliseconds do count in a row filtering method which executes thousands of times.
> 
>      If performance is important, measure.  Don't guess.
> 
Indeed.  I am doing test runs with relatively large data sets.

[toc] | [prev] | [next] | [standalone]


#37716

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2017-12-04 09:29 -0500
Message-ID<p03m3p$ihc$1@dont-email.me>
In reply to#37714
On 12/4/2017 8:32 AM, Eric Douglas wrote:
> On Monday, December 4, 2017 at 8:20:59 AM UTC-5, Eric Sosman wrote:
>>       If it *must* be an ArrayList (and not some other kind of List),
>> you might want to change the last bit to
>>
>> 	.collect(Collectors.toCollection(ArrayList::new));
>>
>> Although the toList() method appears to use ArrayList anyhow, it
>> doesn't guarantee to do so -- meaning that it might use some other
>> List in a future Java, or in circumstances I haven't studies (e.g.,
>> it might behave differently with a parallel stream).
>>
> ok, thanks, I'll keep that in mind.  I'll have to test if the variable can be assigned and if that would be more efficient.  Currently it doesn't matter what kind of list because I made the rowToModelIndex variable final, just calling clear() then addAll().

     If you'd rather clear and repopulate the same List (as opposed
to making a new one each time), you could use forEach():

	rowModelIndex.clear();
	IntStream.range(0, modelRowCount)
             .filter((value) -> include(value))
	    .forEach((value) -> rowModelIndex.add(value);

or

	rowModelIndex.clear();
	IntStream.range(0, modelRowCount)
	    .forEach((value) ->
	        if (include(value)) rowModelIndex.add(value));

I don't know which of these might be faster, or whether either
might be faster than a plain old `for' loop.  (Research project.)

     FWIW, Brian Goetz (who knows far more about JVM performance
issues than I ever will) indicates that object allocation and
collection is cheaper than commonly thought, so there's little
if any advantage to re-using the same List object:

https://www.ibm.com/developerworks/java/library/j-jtp09275/index.html

... which means even more research may be indicated.  (The cited
article is twelve years old, and we may expect that JVM's have
continued to improve meanwhile).

-- 
esosman@comcast-dot-net.invalid
Eleven hundred forty-three days to go.

[toc] | [prev] | [next] | [standalone]


#37717

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-12-04 07:14 -0800
Message-ID<a706de3b-eafe-47c9-8144-b1ceb04bc495@googlegroups.com>
In reply to#37716
On Monday, December 4, 2017 at 9:29:33 AM UTC-5, Eric Sosman wrote:
>      If you'd rather clear and repopulate the same List (as opposed
> to making a new one each time), you could use forEach():
> 
> 	rowModelIndex.clear();
> 	IntStream.range(0, modelRowCount)
>              .filter((value) -> include(value))
> 	    .forEach((value) -> rowModelIndex.add(value);
> 
> or
> 
> 	rowModelIndex.clear();
> 	IntStream.range(0, modelRowCount)
> 	    .forEach((value) ->
> 	        if (include(value)) rowModelIndex.add(value));
> 
> I don't know which of these might be faster, or whether either
> might be faster than a plain old `for' loop.  (Research project.)
> 

Thanks!  I'll check it out.

>      FWIW, Brian Goetz (who knows far more about JVM performance
> issues than I ever will) indicates that object allocation and
> collection is cheaper than commonly thought, so there's little
> if any advantage to re-using the same List object:
> 
> https://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
> 
> ... which means even more research may be indicated.  (The cited
> article is twelve years old, and we may expect that JVM's have
> continued to improve meanwhile).
> 

I'd have to take another look at their code for clear() and addAll(), I would guess generating a new variable might be cheaper, but the functional difference is more important.  I'd have to check if I have something else grabbing a reference to this variable just expecting it to get updated values rather than needing to get the reference to a new variable.  I believe I did that, though offhand can't recall why.

[toc] | [prev] | [next] | [standalone]


#37736

FromSebastian <nowhere@nirvana.org>
Date2017-12-08 15:00 +0100
Message-ID<p0e5us$eiv$1@news.albasani.net>
In reply to#37716
Am 04.12.2017 um 15:29 schrieb Eric Sosman:

>
> I don't know which of these might be faster, or whether either
> might be faster than a plain old `for' loop.  (Research project.)
>
>     FWIW, Brian Goetz (who knows far more about JVM performance
> issues than I ever will) indicates that object allocation and
> collection is cheaper than commonly thought, so there's little
> if any advantage to re-using the same List object:
>
> https://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
>
> ... which means even more research may be indicated.  (The cited
> article is twelve years old, and we may expect that JVM's have
> continued to improve meanwhile).
>

Angelika Langer did some research into the performance of streams vs. 
for loops when JDK 8 came out. It's referenced from this article, which 
puts performance, readability and maintainability into perspective:

https://blog.jooq.org/2015/12/08/3-reasons-why-you-shouldnt-replace-your-for-loops-by-stream-foreach/

-- Sebastian

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web