Collect list of Integer (List<Integer>) to map with Java 8 Stream API - arraylist

I tried to convert a simple List<Integer> to a Map using Java 8 stream API and got the following compile time error:
The method toMap(Function<? super T,? extends K>, Function<? super T,?
extends U>) in the type Collectors is not applicable for the arguments
(Function<Object,Object>, boolean)
My code:
ArrayList<Integer> m_list = new ArrayList<Integer>();
m_list.add(1);
m_list.add(2);
m_list.add(3);
m_list.add(4);
Map<Integer, Boolean> m_map = m_list.stream().collect(
Collectors.toMap(Function.identity(), true));
I also tried the second method below but got the same error.
Map<Integer, Boolean> m_map = m_list.stream().collect(
Collectors.toMap(Integer::intValue, true));
What is the correct way to do this using Java 8 stream API?

You are passing a boolean for the value mapper. You should pass a Function<Integer,Boolean>.
It should be:
Map<Integer, Boolean> m_map = m_list.stream().collect(
Collectors.toMap(Function.identity(), e -> true));

Related

how to reverse the measurement data using MeasurementFilter in Java SDK for Cumulocity Api?

I am using below code to get the latest measurement API details for specific device but its not returning the data in descending order:
import com.cumulocity.sdk.client.measurement.MeasurementFilter;
import com.cumulocity.sdk.client.Platform;
import com.cumulocity.rest.representation.measurement.MeasurementRepresentation;
#Autowired
private Platform platform;
MeasurementFilter filter = new MeasurementFilter().byType("type").bySource("deviceId").byDate(fromDate,dateTo);
Iterable<MeasurementRepresentation> mRep = platform.getMeasurementApi().getMeasurementsByFilter(filter).get().elements(1);
List<MeasurementRepresentation> mRepList = StreamSupport.stream(mRep.spliterator(), false).collect(Collectors.toList());
...
MeasurementFilter api
we can get the latest data using 'revert=true' in Http REST url call..
../measurement/measurements?source={deviceId}&type={type}&dateTo=xxx&dateFrom=xxx&revert=true
How we can use 'revert=true' or other way to get measurement details in order using Cumulocity Java SDK? appreciate your help here.
The SDK currently has no out-of-the-box QueryParam for revert parameter so you have to create it yourself:
import com.cumulocity.sdk.client.Param;
public class RevertParam implements Param {
#Override
public String getName() {
return "revert";
}
}
And then you can combine it with your query. Therefore you to include your Query Param when you use the get() on the MeasurementCollection. You are currently not passing anything but you can pass pageSize and an arbitrary number of QueryParam.
private Iterable<MeasurementRepresentation> getMeasurementByFilterAndQuery(int pageSize, MeasurementFilter filter, QueryParam... queryParam) {
MeasurementCollection collection = measurementApi.getMeasurementByFilter(filter);
Iterable<MeasurementRepresentation> iterable = collection.get(pageSize, queryParam).allPages();
return iterable;
}
private Optional<MeasurementRepresentation> getLastMeasurement(GId source) {
QueryParam revertQueryParam = new QueryParam(new RevertParam(), "true");
MeasurementFilter filter = new MeasurementFilter()
.bySource(source)
.byFromDate(new DateTime(0).toDate());
Iterable<MeasurementRepresentation> iterable = measurementRepository.getMeasurementByFilterAndQuery(1, filter, revertQueryParam);
if (iterable.iterator().hasNext()) {
return Optional.of(iterable.iterator().next());
} else {
return Optional.absent();
}
}
Extending your code it could look like this:
QueryParam revertQueryParam = new QueryParam(new RevertParam(), "true");
MeasurementFilter filter = new MeasurementFilter().byType("type").bySource("deviceId").byDate(fromDate,dateTo);
Iterable<MeasurementRepresentation> mRep = platform.getMeasurementApi().getMeasurementsByFilter(filter).get(1, revertQueryParam);
List<MeasurementRepresentation> mRepList = StreamSupport.stream(mRep.spliterator(), false).collect(Collectors.toList());
What you did with elements is not incorrect but it is not limiting the API call to just return one value. It would query with defaultPageSize (=5) and then on Iterable level limit it to only return one. The elements() function is more for usage when you need more elements than the maxPageSize (=2000). Then it will handle automatic requesting for additional pages and you can just loop through the Iterable.

Graph traversal name to graph name mapping

Is there any API using which I can get graphTraversalName to graphName mapping defined in the script?
I am using the below messy code but it's error-prone if both graphs are using the same underlying storage.
Map<String, String> graphTraversalToNameMap = new ConcurrentHashMap<String, String>();
while(traversalSourceIterator.hasNext()){
String traversalSource = traversalSourceIterator.next();
String currentGraphString = ( (GraphTraversalSource) graphManager.getAsBindings().get(traversalSource)).getGraph().toString();
graphNameTraversalMap.put(currentGraphString, traversalSource);
}
Iterator<String> graphNamesIterator = graphManager.getGraphNames().iterator();
while(graphNamesIterator.hasNext()){
String graphName = graphNamesIterator.next();
String currentGraphString = graphManager.getGraph(graphName).toString();
String traversalSource = graphNameTraversalMap.get(currentGraphString);
graphTraversalToNameMap.put(traversalSource, graphName);
}
Does gremlinExecutor.getScriptEngineManager().getBindings().entrySet() provide order guarantee? I can iterate over this and populate my map
Is there any API using which I can get graphTraversalName to graphName mapping defined in the script?
No. They share the same namespace in Gremlin Server so the relationship gets lost programmatically. You would need to do something like what you are doing but I wouldn't rely on toString() of a Graph for equality. Perhaps use the Graph instance itself? Although that might not work either depending on your situation and what you want for equality as you could have two different Graph configurations pointed at the same data and want to resolve those as the same graph. I'm also not sure that any approach will work generally for all graph systems. Anyway, I think I'd experiment with using Map<Graph, String> graphTraversalToNameMap for your case and see how that goes.
Does gremlinExecutor.getScriptEngineManager().getBindings().entrySet() provide order guarantee?
No as it is backed by a ConcurrentHashMap. You would have to provide your own order.
Underlying storage details can be obtained from the configuration object and can be used for the mapping, sample code:
public class GraphTraversalMappingUtil {
public static void populateGraphTraversalToNameMapping(GraphManager graphManager){
if(graphTraversalToNameMap.size() != 0){
return;
}
Iterator<String> traversalSourceIterator = graphManager.getTraversalSourceNames().iterator();
Map<StorageBackendKey, String> storageKeyToTraversalMap = new HashMap<StorageBackendKey, String>();
while(traversalSourceIterator.hasNext()){
String traversalSource = traversalSourceIterator.next();
StorageBackendKey key = new StorageBackendKey(
graphManager.getTraversalSource(traversalSource).getGraph().configuration());
storageKeyToTraversalMap.put(key, traversalSource);
}
Iterator<String> graphNamesIterator = graphManager.getGraphNames().iterator();
while(graphNamesIterator.hasNext()) {
String graphName = graphNamesIterator.next();
StorageBackendKey key = new StorageBackendKey(
graphManager.getGraph(graphName).configuration());
graphTraversalToNameMap.put(storageKeyToTraversalMap.get(key), graphName);
}
}
}
For full code, refer: https://pastebin.com/7m8hi53p

Use Java8 Stream on JDBCTemplate Results from HIVE

I am using jdbcTemplate to query hive then writing the results to a .csv file. I basically just generate a list of objects then steam the list to write each record to the file.
I will like to stream the results as they coming back from hive and write it to the file instead of wait to get the whole thing then processing it. Can anyone pointing me to the right direction? Thanks!
private List<Avs> queryAvsData(String asSql) {
List<Avs> llistAvs = new ArrayList<Avs>();
List<Map<String, Object>> rows = hiveJdbcTemplate.queryForList(asSql);
Iterator<Map<String, Object>> it = rows.iterator();
while (it.hasNext()) {
Map<String, Object> row = it.next();
Avs laAvs = Avs.builder()
.make((String) row.get("make"))
.model((String) row.get("model"))
.build();
llistAvs.add(laAvs);
}
return llistAvs;
}
It doesn't look like there's a built-in solution, but you can do it. Basically, you wrap the existing functionality in an iterator, and use a spliterator to turn it into a stream. Here's a blog post on the subject:
The code implements Spring’s ResultSetExtractor interface, which is a Single Abstract Method (SAM) interface, allowing the use of a lambda expression to implement it.
The implementation wraps the SQL ResultSet in an iterator, constructs a stream using the Spliterators and StreamSupport utility classes, and applies that to a Function taking a stream of row sets and returning a generic result.
It's possible to stream values from JdbcTemplate. The following example is a service based on Spring Boot 2.4.8.
As, I run into problems (connection leak) using queryForStream then I will put a demo code here just to know that stream must be closed after usage.
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.stream.Stream;
#Service
#RequiredArgsConstructor
public class DataCleaningService {
private final NamedParameterJdbcTemplate jdbcTemplate;
public void doSomeStreaming() {
String nativeQuery = "SELECT string_value FROM my_table WHERE column = :valueToFiler";
Map<String, Object> queryParameters = Map.of("valueToFiler", "my value");
SingleColumnRowMapper<String> stringRowMapper = SingleColumnRowMapper.newInstance(String.class);
try (Stream<String> stringValueStream = jdbcTemplate.queryForStream(nativeQuery, queryParameters, stringRowMapper)) {
stringValueStream.forEach(stringValue -> {
// do the needed action with the value
//..
System.out.printf("My cool value: %s", stringValue);
});
}
}
}

OutOfMemory while using Jackson 1.9

I am using Jackson 1.9. in my web application wherein I require to convert complex objects e.g Spring’s ModelMap, BindingResult, java.uil.Map to JSON String objects.
Please consider the following code snippet where I am attempting one such conversion:
Map<String, Object> methodArgsMap = new HashMap<String, Object>();
methodArgsMap.put("map", map);/*map is an instance of org.springframework.ui.ModelMap*/
methodArgsMap.put("command", command);/*command is an instance of a custom POJO viz.ReportBeanParam*/
methodArgsMap.put("result", result);/*result is an instance of org.springframework.validation.BindingResult*/
The method is JSONProcessUtil. getObjectsAsJSONString(...) implemented as follows :
public final class JSONProcessUtil {
private static ObjectMapper objectMapper;
static {
objectMapper = new ObjectMapper();
/*Start : Configs. suggested by Jackson docs to avoid OutOfMemoryError*/
SerializationConfig serConfig = objectMapper.getSerializationConfig();
serConfig.disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
objectMapper.getJsonFactory().configure(
JsonParser.Feature.INTERN_FIELD_NAMES, false);
objectMapper.getJsonFactory().configure(
JsonParser.Feature.CANONICALIZE_FIELD_NAMES, false);
/*End : Configs. suggested by Jackson docs to avoid OutOfMemoryError*/
}
public static Map<String, String> getObjectsAsJSONString(
Map<String, Object> argsMap) throws JsonGenerationException,
JsonMappingException, IOException {
log.info("Source app.In JSONProcessUtil.getObjectsAsJSONString(...)");
Map<String, String> jsonStrMap = null;
if (!(argsMap == null || argsMap.isEmpty())) {
jsonStrMap = new HashMap<String, String>();
Set<String> keySet = argsMap.keySet();
Iterator<String> iter = keySet.iterator();
String argName = null;
while (iter.hasNext()) {
argName = iter.next();
log.info("Source app. argName = {}, arg = {} ", argName,
argsMap.get(argName));
jsonStrMap.put(argName,
objectMapper.writeValueAsString(argsMap.get(argName)));/*The line giving error*/
log.info("Proceeding to the next arg !");
}
}
log.info("Source app. Exit from JSONProcessUtil.getObjectsAsJSONString(...)");
return jsonStrMap;
}
}
I am getting an OutOfMemoryError as follows :
INFO [http-8080-7] (JSONProcessUtil.java:73) - Source app. argName = result, arg = org.springframework.validation.BeanPropertyBindingResult: 0 errors DEBUG [http-8080-7] (SecurityContextPersistenceFilter.java:89) - SecurityContextHolder now cleared, as request processing completed Feb 20, 2012 5:03:30 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet saas threw exception
java.lang.OutOfMemoryError: Java heap space
at org.codehaus.jackson.util.TextBuffer._charArray(TextBuffer.java:
674)
at org.codehaus.jackson.util.TextBuffer.expand(TextBuffer.java:633)
at org.codehaus.jackson.util.TextBuffer.append(TextBuffer.java:438)
at org.codehaus.jackson.io.SegmentedStringWriter.write(SegmentedStringWriter.java:69)
at org.codehaus.jackson.impl.WriterBasedGenerator._flushBuffer(WriterBasedGenerator.java:1810)
at org.codehaus.jackson.impl.WriterBasedGenerator._writeFieldName(WriterBasedGenerator.java:345)
at org.codehaus.jackson.impl.WriterBasedGenerator.writeFieldName(WriterBasedGenerator.java:217)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:426)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
at org.codehaus.jackson.map.ser.impl.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:121)
at org.codehaus.jackson.map.ser.impl.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:28)
at org.codehaus.jackson.map.ser.ArraySerializers$AsArraySerializer.serialize(ArraySerializers.java:56)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
at org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:287)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:212)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:23)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
at org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:287)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:212)
at org.codehaus.jackson.map.ser.MapSerializer.serialize(MapSerializer.java:23)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428)
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142)
at org.codehaus.jackson.map.ser.MapSerializer.serializeFields(MapSerializer.java:287)
Please guide about resolving the same.
Thanks and regards !
Sounds like you are producing a huge JSON output, which gets buffered in memory.
This based on error message.
Your choices are either:
Use streaming output to avoid buffering it in memory (however, I am not sure if Spring allows you to do this), or
Increase heap size so you have enough memory
Features to disable interning and canonicalization are only relevant for parsing, and you are generating JSON, not parsing.

Geo-targeting with the openx API

I am using the openx api to insert advertisers/campaigns/banners but I cannot seem to find any documentation on geo-targeting a campaign or banner via the API. Can this be done, or am I going to have to start injecting directly into the database.
I did not find anything in the documentation either, however I was able to find how to do it.
Below is the java code. I used the method setBannerTargeting from BannerXmlRpcService.php.
public static String GEO_CONTINENT_LIMITATION = "deliveryLimitations:Geo:Continent";
public static String GEO_COUNTRY_LIMITATION = "deliveryLimitations:Geo:Country";
map = new HashMap();
public static String[] CONTINENTS = new String[]{
"AS","EU","AF","OC","CA","SA","NA","AQ",
};
public static String CONTAINS_OPERATOR = "=~";
public static String OR_LOGICAL_OPERATOR = "or";
..........................
List list = new ArrayList();
HashMap targeting = new HashMap();
targeting.put("logical",Targeting.OR_LOGICAL_OPERATOR);
targeting.put("type",Targeting.GEO_CONTINENT_LIMITATION);
targeting.put("comparison",Targeting.CONTAINS_OPERATOR);
targeting.put("data",Targeting.CONTINENTS[1]);
list.add(targeting);
...........................
map.put("aTargeting",list);
proxy.setTargeting(bannerID,list);