I need to have a Map which is thread safe and can have multiple values. I did write one using MultiMap
as
private MultiMap<String, String> uploadIdETagMap = new MultiValueMap<String, String>();
//Function to get tag value and add to map to that uploadId key
public void uploadPartForMultiPartUpload() {
try {
UploadPartRequest partRequest = new UploadPartRequest();
partRequest = partRequest.withBucketName(bucketName).withInputStream(inputStream).withKey(fileName)
.withPartNumber(partNumber).withUploadId(uploadId).withPartSize(sizeOfData)
.withLastPart(isLastPart);
UploadPartResult result = s3Client.uploadPart(partRequest);
uploadIdETagMap.put(uploadId, result.getPartETag());
} catch (Exception e) {
log.error("Error uploading part: {} in multi part upload.", partNumber, e);
}
}
List<String> tagList = (List<String>) uploadIdETagMap.get(uploadId);
So everytime i will get new tag value for a particular uplaodId key and i need all of those tags at the end and there will be other uploads processing same time.
In the above code, tag
gets added every time as the value of the MultiMap
for specific uploadId
key.
The above code works, but both MultiMap
and MultiValueMap
is deprecated and not thread safe.
So any suggestion how can i achieve this with latest version and thread safety.
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArrayList<>() )
)
.add( "Purple" )
;
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArrayList<>() )
)
.add( "Gold" )
;
personFavoriteColors.toString(): [Purple, Gold]
Map::computeIfAbsent
Java now has multimap behavior built-in with new computeIfAbsent
method defined on the Map
interface.
Define your map.
ConcurrentMap< String , Set< String> > personFavoriteColors = new ConcurrentSkipListMap<>() ;
We are using a Map
implementation that implements the ConcurrentMap
interface for thread-safety as you requested. Java offers two such implementations.
Use a single line to create a new list or set to hold the multiple values.
personFavoriteColors.computeIfAbsent(
"Alice" ,
( x -> new CopyOnWriteArraySet<>() ) // Lambda expression. Run only if needed to run (if absent).
) // Returns the value of a map (a `Set` or `List` when desiring a multimap).
.add( "Purple" )
;
You may access the Set
(or List
) outside of the Map
that owns it. So that Set
(or List
) must also be concurrent.
Here we used a concurrent set, CopyOnWriteArraySet
as our value for the map.
For example:
Set< String > favoriteColorsForAlice = personFavoriteColors.get( "Alice" ) ;
System.out.println( favoriteColorsForAlice ) ;
See this code run live on IdeOne.com.
[Purple, Gold]