mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 13:27:47 +01:00
Adds submap queries to the addressable large cache
This commit is contained in:
@@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentSkipListMap
|
||||
import java.util.function.BiConsumer
|
||||
|
||||
class LargeSoftCache<K, V> : CacheOperations<K, V> {
|
||||
private val cache = ConcurrentSkipListMap<K, WeakReference<V>>()
|
||||
protected val cache = ConcurrentSkipListMap<K, WeakReference<V>>()
|
||||
|
||||
fun keys() = cache.keys
|
||||
|
||||
@@ -125,6 +125,14 @@ class LargeSoftCache<K, V> : CacheOperations<K, V> {
|
||||
cache.forEach(BiConsumerWrapper(this, consumer))
|
||||
}
|
||||
|
||||
override fun forEach(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: BiConsumer<K, V>,
|
||||
) {
|
||||
cache.subMap(from, to).forEach(BiConsumerWrapper(this, consumer))
|
||||
}
|
||||
|
||||
class BiConsumerWrapper<K, V>(
|
||||
val cache: LargeSoftCache<K, V>,
|
||||
val inner: BiConsumer<K, V>,
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.utils.cache.CacheCollectors
|
||||
|
||||
const val START_KEY = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
fun kindStart(
|
||||
kind: Int,
|
||||
pubKey: HexKey,
|
||||
) = Address(kind, pubKey, "")
|
||||
|
||||
fun kindEnd(
|
||||
kind: Int,
|
||||
pubKey: HexKey,
|
||||
) = Address(kind + 1, pubKey, "")
|
||||
|
||||
fun kindStart(kind: Int) = kindStart(kind, START_KEY)
|
||||
|
||||
fun kindEnd(kind: Int) = kindEnd(kind + 1, START_KEY)
|
||||
|
||||
fun LargeSoftCache<Address, AddressableNote>.filterIntoSet(
|
||||
kind: Int,
|
||||
consumer: CacheCollectors.BiFilter<Address, AddressableNote>,
|
||||
): Set<AddressableNote> = filterIntoSet(kindStart(kind), kindEnd(kind), consumer)
|
||||
|
||||
fun LargeSoftCache<Address, AddressableNote>.filterIntoSet(
|
||||
kinds: List<Int>,
|
||||
consumer: CacheCollectors.BiFilter<Address, AddressableNote>,
|
||||
): Set<AddressableNote> {
|
||||
val set = mutableSetOf<AddressableNote>()
|
||||
kinds.forEach {
|
||||
set.addAll(filterIntoSet(kindStart(it), kindEnd(it), consumer))
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
fun LargeSoftCache<Address, AddressableNote>.filterIntoSet(
|
||||
kind: Int,
|
||||
pubKey: HexKey,
|
||||
consumer: CacheCollectors.BiFilter<Address, AddressableNote>,
|
||||
): Set<AddressableNote> = filterIntoSet(kindStart(kind, pubKey), kindEnd(kind, pubKey), consumer)
|
||||
|
||||
fun <R> LargeSoftCache<Address, AddressableNote>.mapNotNullIntoSet(
|
||||
kind: Int,
|
||||
consumer: CacheCollectors.BiMapper<Address, AddressableNote, R?>,
|
||||
): Set<R> = mapNotNullIntoSet(kindStart(kind), kindEnd(kind), consumer)
|
||||
|
||||
fun <R> LargeSoftCache<Address, AddressableNote>.mapNotNullIntoSet(
|
||||
kind: Int,
|
||||
pubKey: HexKey,
|
||||
consumer: CacheCollectors.BiMapper<Address, AddressableNote, R?>,
|
||||
): Set<R> = mapNotNullIntoSet(kindStart(kind, pubKey), kindEnd(kind, pubKey), consumer)
|
||||
@@ -22,7 +22,9 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm
|
||||
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.LocalCache.notes
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
@@ -45,13 +47,11 @@ open class DiscoverLongFormFeedFilter(
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val params = buildFilterParams(account)
|
||||
|
||||
val notes =
|
||||
LocalCache.addressables.filterIntoSet { _, it ->
|
||||
LocalCache.addressables.filterIntoSet(LongTextNoteEvent.KIND) { _, it ->
|
||||
val noteEvent = it.event
|
||||
noteEvent is LongTextNoteEvent && params.match(noteEvent)
|
||||
}
|
||||
|
||||
return sort(notes)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
@@ -45,7 +46,7 @@ open class DiscoverFollowSetsFeedFilter(
|
||||
val params = buildFilterParams(account)
|
||||
|
||||
val notes =
|
||||
LocalCache.addressables.filterIntoSet { _, it ->
|
||||
LocalCache.addressables.filterIntoSet(FollowListEvent.KIND) { _, it ->
|
||||
val noteEvent = it.event
|
||||
noteEvent is FollowListEvent && params.match(noteEvent)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.mapNotNullIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||
@@ -54,7 +55,7 @@ open class DiscoverCommunityFeedFilter(
|
||||
|
||||
// Here we only need to look for CommunityDefinition Events
|
||||
val notes =
|
||||
LocalCache.addressables.mapNotNullIntoSet { key, note ->
|
||||
LocalCache.addressables.mapNotNullIntoSet(CommunityDefinitionEvent.KIND) { key, note ->
|
||||
val noteEvent = note.event
|
||||
if (noteEvent == null && shouldInclude(key, filterParams, note.relays)) {
|
||||
// send unloaded communities to the screen
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ParticipantListBuilder
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
@@ -55,7 +56,7 @@ open class DiscoverNIP89FeedFilter(
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val notes =
|
||||
LocalCache.addressables.filterIntoSet { _, it ->
|
||||
LocalCache.addressables.filterIntoSet(AppDefinitionEvent.KIND) { _, it ->
|
||||
acceptDVM(it)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
|
||||
@@ -46,7 +47,7 @@ open class DiscoverMarketplaceFeedFilter(
|
||||
val params = buildFilterParams(account)
|
||||
|
||||
val notes =
|
||||
LocalCache.addressables.filterIntoSet { _, it ->
|
||||
LocalCache.addressables.filterIntoSet(ClassifiedsEvent.KIND) { _, it ->
|
||||
val noteEvent = it.event
|
||||
noteEvent is ClassifiedsEvent && noteEvent.isWellFormed() && params.match(noteEvent)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.drafts.dal
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
@@ -39,7 +40,7 @@ class DraftEventsFeedFilter(
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val drafts =
|
||||
LocalCache.addressables.filterIntoSet { _, note ->
|
||||
LocalCache.addressables.filterIntoSet(DraftWrapEvent.KIND, account.userProfile().pubkeyHex) { _, note ->
|
||||
acceptableEvent(note)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.dal
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
@@ -45,6 +46,17 @@ import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
|
||||
class HomeNewThreadFeedFilter(
|
||||
val account: Account,
|
||||
) : AdditiveFeedFilter<Note>() {
|
||||
companion object {
|
||||
val ADDRESSABLE_KINDS =
|
||||
listOf(
|
||||
AudioTrackEvent.KIND,
|
||||
InteractiveStoryPrologueEvent.KIND,
|
||||
WikiNoteEvent.KIND,
|
||||
ClassifiedsEvent.KIND,
|
||||
LongTextNoteEvent.KIND,
|
||||
)
|
||||
}
|
||||
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultHomeFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
@@ -67,7 +79,9 @@ class HomeNewThreadFeedFilter(
|
||||
}
|
||||
|
||||
val longFormNotes =
|
||||
LocalCache.addressables.filterIntoSet { _, note ->
|
||||
LocalCache.addressables.filterIntoSet(
|
||||
kinds = ADDRESSABLE_KINDS,
|
||||
) { _, note ->
|
||||
acceptableEvent(note, filterParams)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,11 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||
import com.vitorpamplona.quartz.experimental.forks.forkFromVersion
|
||||
import com.vitorpamplona.quartz.experimental.forks.isForkFromAddressWithPubkey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
@@ -37,6 +39,7 @@ import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||
@@ -47,6 +50,11 @@ import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarRSVPEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarTimeSlotEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
||||
@@ -58,10 +66,25 @@ import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||
import com.vitorpamplona.quartz.nip90Dvms.NIP90ContentDiscoveryRequestEvent
|
||||
import com.vitorpamplona.quartz.nip90Dvms.NIP90ContentDiscoveryResponseEvent
|
||||
import com.vitorpamplona.quartz.nip90Dvms.NIP90StatusEvent
|
||||
import com.vitorpamplona.quartz.nip99Classifieds.ClassifiedsEvent
|
||||
|
||||
class NotificationFeedFilter(
|
||||
val account: Account,
|
||||
) : AdditiveFeedFilter<Note>() {
|
||||
companion object {
|
||||
val ADDRESSABLE_KINDS =
|
||||
listOf(
|
||||
AudioTrackEvent.KIND,
|
||||
WikiNoteEvent.KIND,
|
||||
ClassifiedsEvent.KIND,
|
||||
LongTextNoteEvent.KIND,
|
||||
CalendarTimeSlotEvent.KIND,
|
||||
CalendarDateSlotEvent.KIND,
|
||||
CalendarRSVPEvent.KIND,
|
||||
LiveActivitiesEvent.KIND,
|
||||
)
|
||||
}
|
||||
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultNotificationFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
@@ -83,7 +106,7 @@ class NotificationFeedFilter(
|
||||
LocalCache.notes.filterIntoSet { _, note ->
|
||||
note.event !is AddressableEvent && acceptableEvent(note, filterParams)
|
||||
} +
|
||||
LocalCache.addressables.filterIntoSet { _, note ->
|
||||
LocalCache.addressables.filterIntoSet(ADDRESSABLE_KINDS) { _, note ->
|
||||
acceptableEvent(note, filterParams)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.LocalCache.notes
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.filterIntoSet
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
@@ -67,7 +69,10 @@ class VideoFeedFilter(
|
||||
LocalCache.notes.filterIntoSet { _, it ->
|
||||
acceptableEvent(it, params)
|
||||
} +
|
||||
LocalCache.addressables.filterIntoSet { _, it ->
|
||||
LocalCache.addressables.filterIntoSet(VideoHorizontalEvent.KIND) { _, it ->
|
||||
acceptableEvent(it, params)
|
||||
} +
|
||||
LocalCache.addressables.filterIntoSet(VideoVerticalEvent.KIND) { _, it ->
|
||||
acceptableEvent(it, params)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,108 @@ interface ICacheOperations<K, V> {
|
||||
|
||||
fun <U> associateWith(transform: (K, V) -> U?): Map<K, U?>
|
||||
|
||||
// --
|
||||
// Sub map operations
|
||||
// --
|
||||
|
||||
fun filter(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): List<V>
|
||||
|
||||
fun filterIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): Set<V>
|
||||
|
||||
fun <R> map(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): List<R>
|
||||
|
||||
fun <R> mapNotNull(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, R?>,
|
||||
): List<R>
|
||||
|
||||
fun <R> mapNotNullIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, R?>,
|
||||
): Set<R>
|
||||
|
||||
fun <R> mapFlatten(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, Collection<R>?>,
|
||||
): List<R>
|
||||
|
||||
fun <R> mapFlattenIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, Collection<R>?>,
|
||||
): Set<R>
|
||||
|
||||
fun maxOrNullOf(
|
||||
from: K,
|
||||
to: K,
|
||||
filter: CacheCollectors.BiFilter<K, V>,
|
||||
comparator: Comparator<V>,
|
||||
): V?
|
||||
|
||||
fun sumOf(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiSumOf<K, V>,
|
||||
): Int
|
||||
|
||||
fun sumOfLong(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiSumOfLong<K, V>,
|
||||
): Long
|
||||
|
||||
fun <R> groupBy(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): Map<R, List<V>>
|
||||
|
||||
fun <R> countByGroup(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): Map<R, Int>
|
||||
|
||||
fun <R> sumByGroup(
|
||||
from: K,
|
||||
to: K,
|
||||
groupMap: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
sumOf: CacheCollectors.BiNotNullMapper<K, V, Long>,
|
||||
): Map<R, Long>
|
||||
|
||||
fun count(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): Int
|
||||
|
||||
fun <T, U> associate(
|
||||
from: K,
|
||||
to: K,
|
||||
transform: (K, V) -> Pair<T, U>,
|
||||
): Map<T, U>
|
||||
|
||||
fun <U> associateWith(
|
||||
from: K,
|
||||
to: K,
|
||||
transform: (K, V) -> U?,
|
||||
): Map<K, U?>
|
||||
|
||||
fun joinToString(
|
||||
separator: CharSequence = ", ",
|
||||
prefix: CharSequence = "",
|
||||
|
||||
@@ -36,6 +36,12 @@ class MyBiConsumer<K, V>(
|
||||
interface CacheOperations<K, V> : ICacheOperations<K, V> {
|
||||
fun forEach(consumer: BiConsumer<K, V>)
|
||||
|
||||
fun forEach(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: BiConsumer<K, V>,
|
||||
)
|
||||
|
||||
override fun size(): Int
|
||||
|
||||
override fun forEach(consumer: ICacheBiConsumer<K, V>) {
|
||||
@@ -144,6 +150,171 @@ interface CacheOperations<K, V> : ICacheOperations<K, V> {
|
||||
return runner.results
|
||||
}
|
||||
|
||||
// ----
|
||||
// submap operations
|
||||
// ----
|
||||
override fun filter(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): List<V> {
|
||||
val runner = BiFilterCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun filterIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): Set<V> {
|
||||
val runner = BiFilterUniqueCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> map(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): List<R> {
|
||||
val runner = BiNotNullMapCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> mapNotNull(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, R?>,
|
||||
): List<R> {
|
||||
val runner = BiMapCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> mapNotNullIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, R?>,
|
||||
): Set<R> {
|
||||
val runner = BiMapUniqueCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> mapFlatten(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, Collection<R>?>,
|
||||
): List<R> {
|
||||
val runner = BiMapFlattenCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> mapFlattenIntoSet(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiMapper<K, V, Collection<R>?>,
|
||||
): Set<R> {
|
||||
val runner = BiMapFlattenUniqueCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun maxOrNullOf(
|
||||
from: K,
|
||||
to: K,
|
||||
filter: CacheCollectors.BiFilter<K, V>,
|
||||
comparator: Comparator<V>,
|
||||
): V? {
|
||||
val runner = BiMaxOfCollector(filter, comparator)
|
||||
forEach(from, to, runner)
|
||||
return runner.maxV
|
||||
}
|
||||
|
||||
override fun sumOf(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiSumOf<K, V>,
|
||||
): Int {
|
||||
val runner = BiSumOfCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.sum
|
||||
}
|
||||
|
||||
override fun sumOfLong(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiSumOfLong<K, V>,
|
||||
): Long {
|
||||
val runner = BiSumOfLongCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.sum
|
||||
}
|
||||
|
||||
override fun <R> groupBy(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): Map<R, List<V>> {
|
||||
val runner = BiGroupByCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> countByGroup(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
): Map<R, Int> {
|
||||
val runner = BiCountByGroupCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <R> sumByGroup(
|
||||
from: K,
|
||||
to: K,
|
||||
groupMap: CacheCollectors.BiNotNullMapper<K, V, R>,
|
||||
sumOf: CacheCollectors.BiNotNullMapper<K, V, Long>,
|
||||
): Map<R, Long> {
|
||||
val runner = BiSumByGroupCollector(groupMap, sumOf)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun count(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: CacheCollectors.BiFilter<K, V>,
|
||||
): Int {
|
||||
val runner = BiCountIfCollector(consumer)
|
||||
forEach(from, to, runner)
|
||||
return runner.count
|
||||
}
|
||||
|
||||
override fun <T, U> associate(
|
||||
from: K,
|
||||
to: K,
|
||||
transform: (K, V) -> Pair<T, U>,
|
||||
): Map<T, U> {
|
||||
val runner = BiAssociateCollector(size(), transform)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun <U> associateWith(
|
||||
from: K,
|
||||
to: K,
|
||||
transform: (K, V) -> U?,
|
||||
): Map<K, U?> {
|
||||
val runner = BiAssociateWithCollector(size(), transform)
|
||||
forEach(from, to, runner)
|
||||
return runner.results
|
||||
}
|
||||
|
||||
override fun joinToString(
|
||||
separator: CharSequence,
|
||||
prefix: CharSequence,
|
||||
|
||||
@@ -79,4 +79,12 @@ actual class LargeCache<K, V> : CacheOperations<K, V> {
|
||||
override fun forEach(consumer: BiConsumer<K, V>) {
|
||||
cache.forEach(consumer)
|
||||
}
|
||||
|
||||
override fun forEach(
|
||||
from: K,
|
||||
to: K,
|
||||
consumer: BiConsumer<K, V>,
|
||||
) {
|
||||
cache.subMap(from, to).forEach(consumer)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user