Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter by type #86

Closed
nipafx opened this issue Feb 6, 2025 · 2 comments
Closed

Filter by type #86

nipafx opened this issue Feb 6, 2025 · 2 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@nipafx
Copy link

nipafx commented Feb 6, 2025

Particularly when working with sealed types, I occasionally have the use case to only keep elements in the stream that are an instance of a specified type or of several specified types. The stream's generic type should then of course match that type or those types. This is essentially a filter(instanceof).map(cast).

My gatherer looks like this:

@SafeVarargs
public static <IN, OUT> Gatherer<IN, ?, OUT> only(Class<? extends OUT>... types) {
	return Gatherer.of((_, element, downstream) -> {
		for (var type : types)
			if (type.isInstance(element))
				return downstream.push(type.cast(element));
		return !downstream.isRejecting();
	});
}

Some uses:

Stream.of(1, 2.0, "3")
	.gather(only(Integer.class)) // Stream<Integer>
	.forEach(System.out::println); // 1

Stream.of(1, 2.0, "3")
	.gather(only(Number.class)) // Stream<Number>
	.forEach(System.out::println); // 1 2.0

Stream.of(1, 2.0, "3")
	.gather(only(Double.class, String.class)) // Stream<Serializable>
	.forEach(System.out::println); // 2.0 3

If you'd be interested, I can open a PR. (Or you implement it yourself if that's easier.)

PS: Great project! 😃👍🏾

@tginsberg
Copy link
Owner

Hi @nipafx! Thanks for the kind words, they mean a lot! I'm a big fan of your work to better the Java community!

Interesting you bring this concept up (with examples!!) - I have a whole list of gatherers that fit in the category of "possible with existing operations or gatherers but not super convenient" and this is on the list. Originally I had delayed doing that kind of implementation to see how I felt about it. But I think I'm at the point where I should review the list and see which ones would be useful.

I do like this one a lot, so I'll probably do this and deliver it in 0.9.0. I appreciate the offer of a PR, but I think I'd find it fun to write this myself (this whole project is a side project for me because I enjoy writing libraries, so...).

@tginsberg tginsberg added the enhancement New feature or request label Feb 6, 2025
@tginsberg tginsberg self-assigned this Feb 6, 2025
@nipafx
Copy link
Author

nipafx commented Feb 7, 2025

Thanks for the kind words

Right back at you! 💙🧡

I have a whole list of gatherers that fit in the category of "possible with existing operations or gatherers but not super convenient" and this is on the list

Indeed. In the past I did this with a flatMap(only(...)), where only returned a suitable function. But gatherers are much more suitable. Great that you're looking into it.

this whole project is a side project for me because I enjoy writing libraries, so...

And writing gatherers is fun, too! 😃

tginsberg added a commit that referenced this issue Feb 8, 2025
tginsberg added a commit that referenced this issue Feb 8, 2025
* GH-86: Filter by type
* Documentation
@tginsberg tginsberg added this to the v0.9.0 milestone Feb 8, 2025
tginsberg added a commit that referenced this issue Feb 23, 2025
+ Comprehensive documentation website built with Hugo and Docsy
+ Implement `filterInstanceOf()` to filter a stream by type more easily. Addresses [#86](#86), thanks [@nipafx](https://github.com/nipafx).
+ Implement `groupOrdered()`, and `groupOrderedBy()` to appropriately group elements in the input stream to lists in the output stream. Addresses [#88](#88), thanks [@nipafx](https://github.com/nipafx).
+ Implement `ensureOrdred()` and `ensureOrderedBy()` to ensure the given stream meets an ordering criteria, or fail exceptionally otherwise
+ Implement `filterOrdered()` and `filterOrderedBy()` to remove non-ordered elements from the input stream
+ Implement `window()` to provide more options to windowing functions, namely - ability to specify size, how many to skip each time, and whether to include partial windows
+ Implement `repeat(n)` and `repeatInfinitely()` to repeatedly emit the input stream to the output stream
+ Implement `rotate(n)` rotate the stream either left or right (consumes entire stream)
+ Renamed `everyNth(n)` to `takeEveryNth(n)` and added `dropEveryNth(n)` for completeness
+ Renamed `filterWithIndex()` to `filterIndexed()` to match other indexing Gatherers
+ Renamed `cross()` to `crossWith()` for consistency
+ Renamed `interleave()` to `interleaveWith()` for consistency
+ Renamed `grouping()` to `group()` and `groupingBy()` to `groupBy()` for consistency
+ Renamed `last()` to `takeLast()` to match `dropLast()`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants