GetValue of property in Android - java

I am looking for a solution to get a Value from a Property in Android.
I have an ArrayList of Person and I want to get only the property "name" and add it to an ArrayList of Strings.
The code below is in Xamarin and I am looking for the same thing in android studio. Thanks!
foreach (var s in filter.Nodes)
{
nodeName = s.GetType().GetProperty("Name").GetValue(s).ToString();
}

List<String> names = people.stream()
.map(x -> x.name)
.collect(Collectors.toList());
Also I'm unsure why you're still using Java when Kotlin exists...
val names = people.map { it.name }

Create a Model class which will contain properties name like "public String Name". You can use forEach loop to iterate for that Model class and access the property.
public class User{
#SerializedName("Name")
public String name;
}
MainActivity code will be like
for(User user: "your_response"){
list.add(user.name);
}

Try this
ArrayList<String> List = new ArrayList<String>();
for(Person data: filterList){
List.add(data.name);
}

Related

How can I use java streams to retrieve the value of x names?

I can use the below snippet to retrieve the name if there is 1 entry in the list by retrieving element 0 in the list, however, each NameResponse can have several names (e.g. a first name, a middle name and a surname). How can I retrieve x names associated with one customer? There could be 20 names for argument's sake. I would like to implement using a stream since I am using Java 8, but I am unsure how to implement this. Any suggestions?
private List<String> getNames(Customer customer) {
List<NameResponse> nameResponses = new ArrayList<>();
NameResponse nameResponse = new NameResponse();
nameResponse.setName("Test Name");
nameResponses.add(nameResponse);
customer.setNames(nameResponses);
return List.of(customer.getNames().get(0).getName());
}
Customer class:
private List<NameResponse> names;
NameResponse class:
private String name;
Something like below assuming you have the appropriate getters:
return customer.getNames()
.stream()
.map(NameResponse::getName)
.collect(Collectors.toList());
You could do that using the map operator on the stream and then collect to output a list:
return customer.getNames().stream()
.map(nameResponse -> nameResponse.getName())
.collect(Collectors.toList()));

Filter objects from a list that have the same member

I have a list of objects. The object looks like this:
public class Slots {
String slotType;
Visits visit;
}
public class Visits {
private long visitCode;
private String agendaCode;
private String scheduledTime;
private String resourceType;
private String resourceDescription;
private String visitTypeCode;
...
}
I need to find the elements that have the same agendaCode, visitTypeCode and scheduledTime and for the life of me I can't get it done.
I tried this:
Set<String> agendas = slotsResponse.getContent().stream()
.map(Slots::getVisit)
.map(Visits::getAgendaCode)
.collect(Collectors.toUnmodifiableSet());
Set<String> visitTypeCode = slotsResponse.getContent().stream()
.map(Slots::getVisit)
.map(Visits::getVisitTypeCode)
.collect(Collectors.toUnmodifiableSet());
Set<String> scheduledTime = slotsResponse.getContent().stream()
.map(Slots::getVisit)
.map(Visits::getScheduledTime)
.collect(Collectors.toUnmodifiableSet());
List<Slots> collect = slotsResponse.getContent().stream()
.filter(c -> agendas.contains(c.getVisit().getAgendaCode()))
.filter(c -> visitTypeCode.contains(c.getVisit().getVisitTypeCode()))
.filter(c -> scheduledTime.contains(c.getVisit().getScheduledTime()))
.collect(Collectors.toList());
But it's not doing what I thought it would. Ideally I would have a list of lists, where each sublist is a list of Slots objects that share the same agendaCode, visitTypeCode and scheduledTime. I struggle with functional programming so any help or pointers would be great!
This is Java 11 and I'm also using vavr.
Since you mentioned you're using vavr, here is the vavr way to solve this question.
Supposed you have your io.vavr.collection.List (or Array or Vector or Stream or similar vavr collection) of visits:
List<Visits> visits = ...;
final Map<Tuple3<String, String, String>, List<Visits>> grouped =
visits.groupBy(visit ->
Tuple.of(
visit.getAgendaCode(),
visit.getVisitTypeCode(),
visit.getScheduledTime()
)
);
Or with a java.util.List of visits:
List<Visits> visits = ...;
Map<Tuple3<String, String, String>, List<Visits>> grouped = visits.stream().collect(
Collectors.groupingBy(
visit ->
Tuple.of(
visit.getAgendaCode(),
visit.getVisitTypeCode(),
visit.getScheduledTime()
)
)
);
The easiest way is to define a new class with necessaries fields (agendaCode, visitTypeCode and scheduledTime). Don't forget about equals/hashcode.
public class Visits {
private long visitCode;
private String resourceType;
private String resourceDescription;
private Code code;
...
}
class Code {
private String agendaCode;
private String scheduledTime;
private String visitTypeCode;
...
#Override
public boolean equals(Object o) {...}
#Override
public int hashCode() {...}
}
Then you can use groupingBy like:
Map<Code, List<Slots>> map = slotsResponse.getContent().stream()
.collect(Collectors.groupingBy(s -> s.getVisit().getCode()));
Also you can just implement equals method inside Visits only for agendaCode, visitTypeCode and scheduledTime. In this case use groupingBy by s.getVisit()
I love Ruslan's idea of using Collectors::groupingBy. Nevertheless, I don't like creating a new class or defining a new equals method. Both of them coerces you to a single Collectors::groupingBy version. What if you want to group by other fields in other methods?
Here is a piece of code that should let you overcome this problem:
slotsResponse.getContent()
.stream()
.collect(Collectors.groupingBy(s -> Arrays.asList(s.getVisit().getAgendaCode(), s.getVisit().getVisitTypeCode(), s.getVisit().getScheduledTime())))
.values();
My idea was to create a new container for every needed field (agendaCode, visitTypeCode, scheludedTime) and compare slots on these newly created containers. I would have liked doing so with a simple Object array, but it doesn't work - arrays should be compared with Arrays.equals which is not the comparison method used by Collectors::groupingBy.
Please note that you should store somewhere or use a method to define which fields you want to group by.
The fields you want to group by are all strings. You can define a function which concatenate those fields values and use that as key for your groups. Example
Function<Slots,String> myFunc = s -> s.getVisit().agendaCode + s.getVisit().visitTypeCode + s.getVisit().scheduledTime;
// or s.getVisit().agendaCode +"-"+ s..getVisit().visitTypeCode +"-"+ s.getVisit().scheduledTime;
And then group as below:
Map<String,List<Slots>> result = slotsResponse.getContent().stream()
.collect(Collectors.groupingBy(myFunc));

How can we customize order of count,avg,sum,min and max in DoubleSummaryStatistics object in java8

I am getting below output in following format, which is default I think.
{"count":100,"sum":25640.13,"min":2.65,"max":483.91,"average":256.4013}
But I want to change this format as below.
{"sum":"25640.13","avg":"256.40","max":"483.91","min":"2.65","count":100}
Below code I am using in java class.
#Override
public DoubleSummaryStatistics getStatistic() {
logger.info("Getting statistic");
Set<Entry<Long, Transaction>> endtrySet = statisticHistory.entrySet();
List<Double> amountList = new ArrayList<>();
for (Entry<Long, Transaction> entry : endtrySet) {
if (((entry.getValue().getDate())).isAfter(Instant.now().minusSeconds(windowInMs)))
amountList.add((entry.getValue().getAmount()).doubleValue());
}
return amountList.stream().mapToDouble((x) -> x).summaryStatistics();
}
How can I rearrange the json format?
For more understanding, pasting above method with simple syntax.
Sample Code Method..
public DoubleSummaryStatistics getStatisdtic() {
logger.info("Getting statistic");
Set<BigDecimal> endtrySet = null ; //= getting this from a other resource
List<Double> amountList = new ArrayList<>();
for (BigDecimal entry : endtrySet) {
amountList.add((entry).doubleValue());
}
return amountList.stream().mapToDouble((x) -> x).summaryStatistics();
}
Since you can't edit DoubleSummaryStatistics (you can't add your own json specific annotations inside it), the thing you can do is create your own class MyDoubleSummaryStatistics that would be created from whatever result you want.
But in case you are calling toString on that DoubleSummaryStatistics, why not call each field separately from it, like DoubleSummaryStatistics ::getAverage and the like and build whatever string you need/want.

Short way to create sub-list in java

Is there a shorter way to create sublist from other list?
For example:
I have a Contact obiect, this obiect contain String field of adres
public List<String> getAdreses(long personID) {
List<String> adreses=null;
for(Contact mail : getContacts(personID)){
adreses.add(mail.getMail());
}
return adreses;
}
Try Java Stream:
List<String> adreses = getContacts(personID).stream().map(Contact::getMail).collect(Collectors.toList())

Collect values from list of POJO using Functional interfaces (lambdas)

How can I iterate over list of POJO classes for collecting result of some methods in a standard way to avoid copy past?
I want to have code like this:
//class 'Person' has methods: getNames(), getEmails()
List<Person> people = requester.getPeople(u.getId());
String names = merge(people, Person::getNames);
String emails = merge(people, Person::getEmails);
instead of such copy-pasted logic:
List<Person> people = requester.getPeople(u.getId());
Set<String> namesAll = new HashSet<>();
Set<String> emailsAll = new HashSet<>();
for (Person p : people) {
if(p.getNames()!=null) {
phonesAll.addAll(p.getNames());
}
if(p.getEmails()!=null) {
emailsAll.addAll(p.getEmails());
}
}
String names = Joiner.on(", ").skipNulls().join(namesAll);
String emails = Joiner.on(", ").skipNulls().join(emailsAll);
Thus, is it possible to implement some standard approach for iterating and processing special method of POJO in list that could be reused?
If I understand you correctly, you want something like this :
String names = people.stream().flatMap(p->p.getNames().stream()).distinct().collect(Collectors.joining(", "));
Now, if you want to save typing that line for each property, you can have this merge method as you suggested :
public static String merge (List<Person> people, Function<Person, Collection<String>> mapper)
{
return people.stream().flatMap(p->mapper.apply(p).stream()).distinct().collect(Collectors.joining(", "));
}
This would make your first snippet work.
Now, you can make this method generic :
public static <T> String merge (List<T> list, Function<T, Collection<String>> mapper)
{
return list.stream().flatMap(p->mapper.apply(p).stream()).distinct().collect(Collectors.joining(", "));
}
I think this should work (haven't tested it).

Categories

Resources