Java 8 Stream: How to get a new list from one list property in a list - java-8

I'm new to java 8 and meet a problem trouble me a lot:
I've a List like below:
List<objMain>
class objMain{
Long rid;
List<objUser> list;
String rname;
}
class objUser{
String userid;
}
now,I want get a new List like below:
List<objUserMain>
class objUserMain{
Long rid;
String rname;
String userid;
}
How can I do this by java 8 stream? Thanks anyone answer me.

It seems as though you want to map each objMain instance into an objUserMain type.
In order to accomplish the task at hand, you'll need to utilise flatMap along with map then collect to a list implementation.
Assuming you have getters and setter where necessary then you can perform the following logic to get the required result.
List<objUserMain> result =
objMainsList.stream()
.flatMap(obj -> obj.getList().stream().map(e -> {
objUserMain user = new objUserMain();
user.setRid(obj.getRid());
user.setRname(obj.getRname());
user.setUserid(e.getUserid());
return user;
})).collect(Collectors.toList());

You can do this using streams the following way
public static List convert(List existing, Function func) {
return existing.stream().map(func).collect(Collectors.toList());
}
The above method will help you to convert your list from one object type to another. The parameters to this is the initial object you want to convert and the method you want to use for conversion. Import the following in you main class
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.function.*;
Now call the method for conversion the following way in the main class that you are trying to convert
List result=convert(newList,
l->{
objUserMain r=new objUserMain();
r.rid=l.rid;
r.rname=l.rname;
r.userid=l.list.get(0).userid;
return r;});
System.out.println(result.get(0).rid);
System.out.println(result.get(0).rname);
System.out.println(result.get(0).userid);
The above is a mixture of lambda functions and streams to allow you to convert object from one type to another. Let me know if you have any queries then I am happy to help. Happy coding.

Related

How do I create associations in gRPC proto files?

I'm might be going about it the wrong way, but I want to define a relationship between two or more structs (messages).
Using StackOverflow as an example, let's say I had a LabelService for CRUD actions on labels. I also have a QuestionService where a Question can have Labels. Let's also assume I have a UserService and a User can also have labels attached
# label.proto
service LabelService {
rpc CreateLabel() returns();
...etc
}
message Label {
string text = 1;
}
But now I want to create my QuestionService and Question message. Do I associate the two files some how or is this level of association done in the go code?
# question.proto
service QuestionService {
rpc CreateQuestion() returns();
...etc
}
message Question {
string text = 1;
repeat Label labels = 2 # <-- how to do this?
}
# user.proto
service UserService {
rpc CreateQuestion() returns();
...etc
}
message User {
string name = 1;
repeat Label labels = 2 # <-- how to do this?
}
I think I'm confused because for REST APIs and using gorm.io for example, I would setup the associations in the structs and have gorm.io create the tables.
From the docs:
import "myproject/other_protos.proto";
so just simply add an import in your question.proto to your user.proto. It's no different than when importing other standard proto definitions like timestamp and duration:
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
Did you already import user.proto in question.proto?
in question.proto
import "user.proto" <- i think you can use Label labels

Jackson XML "Undeclared general entity" caused by custom entity

I'm deserializing a large XML file (not mine) and it contains custom entities defined as:
<!ENTITY math "mathematics">
and elements used this way:
<field>&math;</field>
When I try to deserialize it by:
XmlMapper xmlMapper = new XmlMapper();
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return xmlMapper.readValue(classloader.getResourceAsStream("file.xml"), MyClass.class);
I get this error:
com.fasterxml.jackson.databind.JsonMappingException: Undeclared general entity "math"
I think it might be a security measure to prevent Xml External Entity injections.
Is there a way to mark these custom entities as valid? Like create an Enum for them or something?
If not, is there a flag to just parse these as Strings?
Update:
I was able to work around this problem by basically doing a find-replace on the text file. It's quite an ugly solution and if anyone has a better idea, I'm all ears. :)
I know it may be a little late, but just in case someone else is stuck on the same issue:
You have to set a custom XMLResolver as XMLInputFactory's property:
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.ctc.wstx.api.WstxInputProperties;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
var xmlMapper = new XmlMapper();
xmlMapper.getFactory().getXMLInputFactory().setProperty(
WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER,
new XMLResolver() {
#Override
public Object resolveEntity(String publicId, String systemId, String baseUri, String ns) throws XMLStreamException {
// replace the entity with a string of your choice, e.g.
switch (ns) {
case "nbsp":
return " ";
default:
return "";
}
// some useful tool is org.apache.commons.text.StringEscapeUtils
// e.g.
// return StringEscapeUtils.escapeXml10(StringEscapeUtils.unescapeHtml4('&' + ns + ';'));
}
}
);
// then xmlMapper.readValue....

How can I make changes in the GUI with background work in JavaFX?

From all the searching and reading it’s clear that I need to call Platform.runLater() to change the GUI. It also appears I need to use the Runnable interface. Perhaps I should also use Tasks?
But I can’t figure out how exactly I should use them. Plus, I’m not sure which class I should put them in. I’m super new to JavaFX.
My trial JavaFX project has only a Label and a TextField. Label contains a question and the TextField is for answering. Simple enough.
I ran into the problem here:
The answer checking method is in a separate class. I can’t figure out how I can access the components of the GUI/FXML and change them. The methods in the other classes are static while the components of the GUI/FXML are non-static.
Since my actual project would have many quizzes, I'm keen on using separate classes for checking answers.
Only 3 small classes are relevant here:
The “Launcher” class which contains the main method.
The “ViewController” class for the FXML file as well as some methods.
The “Ans” class which has a method to check the answer input.
In which class should I put the Platform.runLater()? And how would the code be?
I’ll just share the code of the “Ans” and the “ViewController” classes.
Ans (The background works are supposed to happen in this file. In the comments, I've mentioned what I want to do but unable to do. For example, I want to set the Label text from there but I can't. Since I have no idea how to do it I've just put a System.out.Println there. In the comments next to it, I've mentioned what I actually want to do.)
package com.dan.ans;
import com.dan.qn.Qn;
import com.dan.view.ViewController;
public class Ans {
public static void checkAns() {
// Checks if the ans is correct.
if (ViewController.getTextFieldInput().equalsIgnoreCase(Qn.getAns())) {
System.out.println("Correct!"); // Here I want the label to say 'Correct!' rather than it be print out in the console.
Qn.setQuestion(); // This gets the next question from the database. But again, I don't know how to make the changes show on the screen. (In the actual code I'd have a separate Label for each of these things)
} else { // Runs if it's not correct.
System.out.println("Incorrect!"); // Here I want the label to say 'Incorrect' rather than it be print out in the console.
}
}
}
ViewController
package com.dan.view;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import com.dan.ans.Ans;
import com.dan.qn.Qn;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class ViewController implements Initializable {
private static String textFieldInput; // I don't know how to access the typed info in the textField from another class. So I store it here and get it from it.
// This is the getter I use for it. (See above)
public static String getTextFieldInput() {
return textFieldInput;
}
#FXML
private Label label;
#FXML
private TextField textField;
#Override
public void initialize(URL location, ResourceBundle resources) {
Qn.setQuestion(); // This method is in the Qn class. It retrieves data from the db file and keeps them in variables.
label.setText(Qn.getQn()); // This sets the label's text using the retrieved data. So you see the first question when the program opens.
}
// Event Listener on TextField[#textField].onAction
public void enter(ActionEvent event) throws IOException {
textFieldInput = textField.getText(); // Stores the typed info in the variable to be accessed from elsewhere.
Ans.checkAns(); // Runs the checkAns to check if the typed answer is correct or not.
}
}
The “Launcher” method just looks like any method with a main class. So I haven’t shared its code here.
Could someone please show me how I can update the components in the GUI from other classes such as “Ans”? I’m pretty sure I should use Platform.runLater() and Runnable. Also may be Tasks. I’ve seen several examples but it’s not clear how I can use it this context.
Thanks a lot in advance! :)
It's not really particularly clear what the issue is here. The natural (to me, anyway) approach would simply be to make the checkAnswer(...) method a method that simply "does what it says on the box", i.e. that takes an answer as a parameter, checks it, and returns a value to the caller indicating if it is correct.
That way you can also avoid all the ugly static hacks.
public class Ans {
public boolean checkAns(String answer) {
// not really sure what Qn is here, but you can also clean this up and
// get rid of the static methods
if (answer.equalsIgnoreCase(Qn.getAns()) {
// not sure if this really belongs here?
Qn.setQuestion(); // really takes no parameters? Sets it to what, then?
return true ;
} else {
return false ;
}
}
}
And then in your controller, you can just do
public class ViewController implements Initializable {
private Ans ans ;
#FXML
private Label label;
#FXML
private TextField textField;
#Override
public void initialize(URL location, ResourceBundle resources) {
ans = new Ans();
// ...
}
// ...
public void enter(ActionEvent event) {
if (ans.checkAns(textField.getText())) {
// update UI to show answer was correct, etc
} else {
// update UI to show answer was incorrect...
}
}
// ...
}
Note how this allows you to maintain proper separation of concerns: the Ans class doesn't need to know anything at all about the UI (which it should not know about at all), and all the UI-specific code is encapsulated in the controller class where it belongs.
It's not really clear why you are asking about Platform.runLater(...) and using Task, since none of the code you posted appears to involve any background threads (i.e. none of this code seems to take an appreciable amount of time to run). If, for example, the checkAns(...) method was doing some remote lookup and did take time to run, you would execute it in a Task and update the UI from the task's onSucceeded handler. See, e.g. Using threads to make database requests. Your question really seems to be more about basic OO design and how to define the relationships between different objects, though; I don't think you are actually asking about threading at all.

MongoDB - override default Serializer for a C# primitive type

I'd like to change the representation of C# Doubles to rounded Int64 with a four decimal place shift in the serialization C# Driver's stack for MongoDB. In other words, store (Double)29.99 as (Int64)299900
I'd like this to be transparent to my app. I've had a look at custom serializers but I don't want to override everything and then switch on the Type with fallback to the default, as that's a bit messy.
I can see that RegisterSerializer() won't let me add one for an existing type, and that BsonDefaultSerializationProvider has a static list of primitive serializers and it's marked as internal with private members so I can't easily subclass.
I can also see that it's possible to RepresentAs Int64 for Doubles, but this is a cast not a conversion. I need essentially a cast AND a conversion in both serialization directions.
I wish I could just give the default serializer a custom serializer to override one of it's own, but that would mean a dirty hack.
Am I missing a really easy way?
You can definitely do this, you just have to get the timing right. When the driver starts up there are no serializers registered. When it needs a serializer, it looks it up in the dictionary where it keeps track of the serializers it knows about (i.e. the ones that have been registered). Only it it can't find one in the dictionary does it start figuring out where to get one (including calling the serialization providers) and if it finds one it registers it.
The limitation in RegisterSerializer is there so that you can't replace an existing serializer that has already been used. But that doesn't mean you can't register your own if you do it early enough.
However, keep in mind that registering a serializer is a global operation, so if you register a custom serializer for double it will be used for all doubles, which could lead to unexpected results!
Anyway, you could write the custom serializer something like this:
public class CustomDoubleSerializer : BsonBaseSerializer
{
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
var rep = bsonReader.ReadInt64();
return rep / 100.0;
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var rep = (long)((double)value * 100);
bsonWriter.WriteInt64(rep);
}
}
And register it like this:
BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());
You could test it using the following class:
public class C
{
public int Id;
public double X;
}
and this code:
BsonSerializer.RegisterSerializer(typeof(double), new CustomDoubleSerializer());
var c = new C { Id = 1, X = 29.99 };
var json = c.ToJson();
Console.WriteLine(json);
var r = BsonSerializer.Deserialize<C>(json);
Console.WriteLine(r.X);
You can also use your own serialization provider to tell Mongo which serializer to use for certain types, which I ended up doing to mitigate some of the timing issues mentioned when trying to override existing serializers. Here's an example of a serialisation provider that overrides how to serialize decimals:
public class CustomSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (type == typeof(decimal)) return new DecimalSerializer(BsonType.Decimal128);
return null; // falls back to Mongo defaults
}
}
If you return null from your custom serialization provider, it will fall back to using Mongo's default serialization provider.
Once you've written your provider, you just need to register it:
BsonSerializer.RegisterSerializationProvider(new CustomSerializationProvider());
I looked through the latest iteration of the driver's code and checked if there's some sort of backdoor to set custom serializers. I am afraid there's none; you should open an issue in the project's bug tracker if you think this needs to be looked at for future iterations of the driver (https://jira.mongodb.org/).
Personally, I'd open a ticket -- and if a quick workaround is necessary or required, I'd subclass DoubleSerializer, implement the new behavior, and then use Reflection to inject it into either MongoDB.Bson.Serialization.Serializers.DoubleSerializer.__instance or MongoDB.Bson.Serialization.BsonDefaultSerializationProvider.__serializers.

Is there any way to clean up the following generic method using any of the new C# 4 features?

I've just modified a method for handling my DDD commands (previously it had no return type):
public static CommandResult<TReturn> Execute<TCommand, TReturn>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
The method is fine, and does what I want it to do, however using it creates some fugly code:
CommandResult<Customer> result =
DomainCommands.Execute<CustomerCreateCommand, Customer>
(
new CustomerCreateCommand(message)
);
Before I added the Customer return type TReturn, it was nice and tidy and the method could infer the types from its usage. However that's no longer possible.
Is there any way using any new C# features that I could rewrite the above to make it tidier, i.e. using Func, Action, Expression, etc? I'm probably expecting the impossible, but I'm getting fed up of writing so much code to just call a single method that used to be very simple.
One option to reduce it slightly is to have a static generic type for the type parameter that can't be inferred, allowing you to have a generic method with just one type parameter that can be inferred:
public static class DomainCommands<TReturn>
{
public static CommandResult<TReturn> Execute<TCommand>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
}
Then:
var result = DomainCommands<Customer>.Execute(new CustomerCreateCommand(msg));
It's not much nicer, but it's slightly better. Of course, if the domain command type itself could be generic, that might help - so CustomerCreateCommand would implement IDomainCommand<Customer> for example. If you still needed a nongeneric IDomainCommand, you could make IDomainCommand<T> derive from IDomainCommand.

Resources