All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.hash.serialization.SetMarshaller Maven / Gradle / Ivy

/*
 * Copyright 2012-2018 Chronicle Map Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.openhft.chronicle.hash.serialization;

import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.wire.WireIn;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;

import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded;

/**
 * Marshaller of {@code Set}. Uses {@link HashSet} (hence default element objects' equality and
 * {@code hashCode()}) as the set implementation to deserialize into.
 * 

*

This marshaller supports multimap emulation on top of Chronicle Map, that is possible but * inefficient. See the * README section. *

*

Usage:

{@code
 * SetMarshaller valueMarshaller = SetMarshaller.of(
 *     new StringBytesReader(), CharSequenceBytesWriter.INSTANCE);
 * ChronicleMap> map = ChronicleMap
 *     .of(String.class, (Class>) (Class) Set.class)
 *     .averageKey("fruits")
 *     .valueMarshaller(valueMarshaller)
 *     .averageValue(ImmutableSet.of("apples", "bananas", "grapes"))
 *     .entries(10_000)
 *     .create();
 * }
*

*

Look for pre-defined element marshallers in {@link * net.openhft.chronicle.hash.serialization.impl} package. This package is not included into * Javadocs, but present in Chronicle Map distribution. If there are no existing marshallers for * your {@code Set} element type, define {@link BytesReader} and {@link BytesWriter} yourself. * * @param the element type of serialized Sets * @see ListMarshaller * @see MapMarshaller */ public final class SetMarshaller implements BytesReader>, BytesWriter>, StatefulCopyable> { // Config fields private BytesReader elementReader; private BytesWriter elementWriter; /** * Cache field */ private transient Deque orderedElements; /** * Constructs a {@code SetMarshaller} with the given set elements' serializers. *

*

Use static factory {@link #of(BytesReader, BytesWriter)} instead of this constructor * directly. * * @param elementReader set elements' reader * @param elementWriter set elements' writer */ public SetMarshaller(BytesReader elementReader, BytesWriter elementWriter) { this.elementReader = elementReader; this.elementWriter = elementWriter; initTransients(); } /** * Returns a {@code SetMarshaller} which uses the given set elements' serializers. * * @param elementReader set elements' reader * @param elementWriter set elements' writer * @param type of set elements * @return a {@code SetMarshaller} which uses the given set elements' serializers */ public static SetMarshaller of( BytesReader elementReader, BytesWriter elementWriter) { return new SetMarshaller<>(elementReader, elementWriter); } /** * Returns a {@code SetMarshaller} which uses the given marshaller as both reader and writer of * set elements. Example:


     * ChronicleMap
     *     .of(String.class,{@code (Class>)} ((Class) Set.class))
     *     .valueMarshaller(SetMarshaller.of(IntegerMarshaller.INSTANCE))
     *     ...
* * @param elementMarshaller set elements' marshaller * @param type of set elements * @param type of set elements' marshaller * @return a {@code SetMarshaller} which uses the given set elements' marshaller */ public static & BytesWriter> SetMarshaller of( M elementMarshaller) { return of(elementMarshaller, elementMarshaller); } private void initTransients() { orderedElements = new ArrayDeque<>(); } @NotNull @Override public Set read(Bytes in, @Nullable Set using) { int size = in.readInt(); if (using == null) { using = new HashSet<>((int) (size / 0.75)); for (int i = 0; i < size; i++) { using.add(elementReader.read(in, null)); } } else { orderedElements.addAll(using); using.clear(); for (int i = 0; i < size; i++) { using.add(elementReader.read(in, orderedElements.pollFirst())); } orderedElements.clear(); // for GC, avoid zombie object links } return using; } @Override public void write(Bytes out, @NotNull Set toWrite) { out.writeInt(toWrite.size()); toWrite.forEach(e -> elementWriter.write(out, e)); } @Override public SetMarshaller copy() { return new SetMarshaller<>(copyIfNeeded(elementReader), copyIfNeeded(elementWriter)); } @Override public void readMarshallable(@NotNull WireIn wireIn) { elementReader = wireIn.read(() -> "elementReader").typedMarshallable(); elementWriter = wireIn.read(() -> "elementWriter").typedMarshallable(); initTransients(); } @Override public void writeMarshallable(@NotNull WireOut wireOut) { wireOut.write(() -> "elementReader").typedMarshallable(elementReader); wireOut.write(() -> "elementWriter").typedMarshallable(elementWriter); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy