In the code bellow there is a statement like this: .toArray(Bicycle[]::new). What would be the Lambda equivalent to this statment?
I checked that toArray receives a implementation of IntFunction. If I undertood right IntFunction is an Interface Functional that has a apply method that could receive an int and return a Bicycle[]. I don't know what is this int that it receives to try to mount the Lambda equivalent.
package br.com.testes;
import java.util.Arrays;
import java.util.List;
public class TesteMethodReference {
public static void main(String[] args) {
List<String> bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");
Bicycle[] bicycles = bikeBrands.stream()
.map(Bicycle::new) //the same .map((brand) -> new Bicycle(brand))
.toArray(Bicycle[]::new); //WHAT IS THE LAMBDA EQUIVALENT?
System.out.println(Arrays.deepToString(bicycles));
}
}
class Bicycle {
private String brand;
public Bicycle(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
#Override
public String toString() {
return "Bicycle [brand=" + brand + "]";
}
}
May anyone help me to understand it?
Thank you
The API note from the documentation of <A> A[] toArray(IntFunction<A[]> generator)
The generator function takes an integer, which is the size
of the desired array, and produces an array of the desired size.
which is equivalent to what Bergi pointed out in the comments as well:
.toArray(size -> new Bicycle[size])
Related
I want to read in a csv file once, and later request information from it. Later this is going to be in a website/Rest-API.
I am new to the world of java-website-development, but I hope this way is the way to do it:
I create a class that reads in the data (I want that this happens once, so I use a static variable for that).
When the csv is read in by opencsv, the data are stored in a bean. For this I create the Car-class as a bean.
I use a third class to do the processing and the logic. Later this is supposed to be the website that processes the data.
Here are the classes:
The bean:
Car.java
package org.example;
import com.opencsv.bean.CsvBindByName;
import java.math.BigDecimal;
public class Car {
#CsvBindByName
private int id;
#CsvBindByName(column = "name")
private String brand;
#CsvBindByName
private BigDecimal price;
public int getId() {
return id;
}
public String getBrand() {
return brand;
}
public BigDecimal getPrice() {
return price;
}
public void setId(int id) {
this.id = id;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setBrand(String brand) {
this.brand = brand;
}
#Override
public String toString() {
return "Car{" +
"id=" + id +
", brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
abc.csv:
id,name,price
1,Audi,52642
2,Mercedes,57127
3,Skoda,9000
4,Volvo,29000
5,Bentley,350000
6,Citroen,21000
7,Hummer,41400
8,Volkswagen,21600
9,Toyota,26700
ReadCSVFile.java
package org.example;
import com.opencsv.bean.CsvToBeanBuilder;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.List;
public class ReadCSVFile {
static String fileName = "src/main/resources/abc.csv";
public static List<Car> cars;
static {
try {
cars = new CsvToBeanBuilder(new FileReader(fileName))
.withType(Car.class).build().parse();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}
Main.java
package org.example;
import com.opencsv.CSVReader;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
System.out.println();
for (Car car : ReadCSVFile.cars) {
System.out.println(car.toString());
}
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 10; i++) {
System.out.println("Enter id to get more details about the car.");
int id_number = sc.nextInt();
System.out.println("Your selected id is "+id_number);
Car selected_car = null;
for (Car car : ReadCSVFile.cars) {
if (car.getId() == id_number) {
selected_car = car;
}
}
if (selected_car == null) {
System.out.println("No car found that matches your id.");
} else {
System.out.println("Selected car matches: " + selected_car.toString());
}
System.out.println();
}
}
}
This works fine, but when I add a constructor in the Car.java
public Car(int id, String brand, BigDecimal price) {
this.id = id;
this.brand = brand;
this.price = price;
}
then I get an error: Caused by: java.lang.RuntimeException: com.opencsv.exceptions.CsvBeanIntrospectionException: Instantiierung des angegebenen Typs (und eventuell vorhandene Untertypen) ist unm�glich.
I do not know how to switch this error message to English; it means something like "It is not possible to instantiate the wanted type (and possibly also present subtypes)".
Does opencsv generally have problems with constructors? Is this a wanted behaviour? Do beans generally lack constructors? Because I feel like I want to have a constructor in the future in my class...
Please feel free to add comments about my general approach how I organize the code.
OpenCSV‘s introspection works by creating object instances via a no-args constructor. Therefore, you are required to provide one, even if you have specialized constructors as posted in your question.
By default, there will be a no-arg constructor in Java, however, once you have a custom one, the no-arg one must be explicitly defined in your Java class.
To cure the problem, just add back in a no-arg constructor, eg in a protected form:
protected Car() {}
This way, the code should just work fine at runtime.
package com.pr.trio;
import java.util.List;
public class lalala {
private List<SegmentationFieldValue> segmentationFieldValues;
public static class SegmentationFieldValue {
private Integer segmentationFieldId;
private Integer segmentationFieldGroupId;
private String value;
public Integer getSegmentationFieldId() {
return segmentationFieldId;
}
public void setSegmentationFieldId(Integer segmentationFieldId) {
this.segmentationFieldId = segmentationFieldId;
}
public Integer getSegmentationFieldGroupId() {
return segmentationFieldGroupId;
}
public void setSegmentationFieldGroupId(Integer segmentationFieldGroupId) {
this.segmentationFieldGroupId = segmentationFieldGroupId;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public List<SegmentationFieldValue> getSegmentationFieldValues() {
return segmentationFieldValues;
}
public void setSegmentationFieldValues(List<SegmentationFieldValue> segmentationFieldValues) {
this.segmentationFieldValues = segmentationFieldValues;
}
}
package com.pr.trio;
import java.util.Arrays;
public class kk {
public static void main(String[] args) {
lalala l1 = new lalala();
//currently passed as an empty array, want to set SegmentationFieldId & value here from inner class
l1.setSegmentationFieldValues(Arrays.asList());
//lalala.SegmentationFieldValue.this.setSegmentationFieldId(15);
System.out.println(l1.getSegmentationFieldValues());
}
}
So here, I'm not able to pass values for the segmentation field instead of the empty array, gives an error. So how can I set the values from the inner class fields & pass it to my list?
Seeing as your SegmentationFieldValue class is public, it's trivial to use it inside another class, there are basically two ways to go about this:
The first is to import the inner class:
import com.pr.trio.lalala.SegmentationFieldValue;
The second is to qualify the classname whenever you use it:
lalala.SegmentationFieldValue a = new lalala.SegmentationFieldValue();
You can then call the setters on this class, and use the objects in your call to setSegmentationFieldValues:
lalala.SegmentationFieldValue a = new lalala.SegmentationFieldValue();
a.setSegmentationFieldId(1);
a.setSegmentationFieldGroupId(1);
a.setValue("a");
lalala.SegmentationFieldValue b = new lalala.SegmentationFieldValue();
b.setSegmentationFieldId(2);
b.setSegmentationFieldGroupId(1);
b.setValue("b");
l1.setSegmentationFieldValues(Arrays.asList(a, b));
Judging from your comment code, you also seem to be looking for a shorthand way to add an element to your list. A simple implementation could look like this (in class lalala):
public void addSegmentationFieldValue(Integer id, Integer groupId, String value)
{
if (segmentationFieldValues == null)
{
segmentationFieldValues = new ArrayList<>();
}
SegmentationFieldValue result = new SegmentationFieldValue();
result.setSegmentationFieldId(id);
result.setSegmentationFieldGroupId(groupId);
result.setValue(value);
segmentationFieldValues.add(result);
}
After which you can do the following in the main method of k1:
l1.addSegmentationFieldValue(1, 1, "a");
I want to call method name nameStartingWithPrefix() which is inside filter and its definition will be in Filter class.
All ArrayList describes in main(), but the list is not passed as in an argument, how can I call in List of names inside Filter.nameStartingWithPrefix().
Syntax is given like:
names is name of ArrayList which is inside main()
names.stream()
.filter(Filter.nameStartingWithPrefix(scanner.nextLine()))
.map(Mapper.getDistinctCharactersCount())
.forEachOrdered(System.out::println);
Below is code sample:
public class FilterMapper {
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
List<String> names = Arrays.asList(
"aaryanna",
"aayanna",
"airianna",
"alassandra",
"allanna",
"allannah",
"allessandra",
"allianna",
"allyanna",
"anastaisa",
"anastashia",
"anastasia",
"annabella",
"annabelle",
"annebelle"
);
names.stream()
.filter(Filter.nameStartingWithPrefix(scanner.nextLine()))
.map(Mapper.getDistinctCharactersCount())
.forEachOrdered(System.out::println);
}
}
class Filter{
public static String nameStartingWithPrefix(String prefix)
{
}
}
Expected like, I have to write a code on Filter method which filters the names on the basis of prefix given by the user in runtime.
But I am unable to access list on the basis of given code. can you please help me how to access List of names inside the Filter class.
I think List should be passed in arguments of (Filter.nameStartingWithPrefix(scanner.nextLine()))
but its not there.
The Filter and Mapper implementation is followed as -
class Filter {
public static Predicate<String> nameStartingWithPrefix(String prefix) {
return n -> n.startsWith(prefix);
}
}
class Mapper {
public static Function<String, CharactersCount> getDistinctCharactersCount() {
return s -> new CharactersCount(s, (int)s.chars().distinct().count());
}
}
class CharactersCount {
private final String name;
private final Integer distinctCharacterCount;
public CharactersCount(String name, Integer distinctCharacterCount) {
this.name = name;
this.distinctCharacterCount = distinctCharacterCount;
}
#Override
public String toString() {
return "\"" + this.name + "\" has " + this.distinctCharacterCount + " distinct characters.";
}
}
Since you are using a Custom Filter Class to invoke the filter over the stream.
filter function requires a Predicate, therefore you will need to create a custom predicate and return it from the nameStartingWithPrefix function.
In the same way, you will require to create a Function for mapper and will return it from the function.
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.function.Function;
import java.util.function.Predicate;
class Filter {
public static Predicate<String> nameStartingWithPrefix(String nextLine) {
return new Predicate<String>() {
#Override
public boolean test(String t) {
// System.out.println(t);
return t.startsWith(nextLine);
}
};
}
}
public class Solution1 {
private static final Scanner scanner = new Scanner(System.in);
#SuppressWarnings("unchecked")
public static void main(String[] args) {
List<String> names = Arrays.asList(
"aaryanna",
"aayanna",
"airianna",
"alassandra",
"allanna",
"allannah",
"allessandra",
"allianna",
"allyanna",
"anastaisa",
"anastashia",
"anastasia",
"annabella",
"annabelle",
"annebelle"
);
names.stream().filter(Filter.nameStartingWithPrefix(scanner.nextLine()))
.map(Mapper.getDistinctCharactersCount()).forEachOrdered(System.out::println);
}
}
For further clarification for filter and map please check out below links:
Documentation for Predicate Functions : https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#test-T-
Video Explanation for Map : https://www.youtube.com/watch?v=bTTNVP_ORr8
Video Explanation for Filter : https://www.youtube.com/watch?v=vHwToYEYvsU
Note: Please follow Stackoverflow guidelines to ask questions.
small correction in Mapper class
it should be like this (just we need to create object and we need to enclose inner class and methods)
class Mapper {
public static Function<String, CharactersCount> getDistinctCharactersCount() {
FilterMapper fm = new FilterMapper();
return s -> fm.new CharactersCount(s, (int) s.chars().distinct().count());
}
}
Basically sorting could be done by following:
Collections.sort(List);
But my scenario is little bit different. I have a List which contains following objects.
Sample Code 1:
public class GetTraders {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
I have a class which will give value for above list as follow:
public Class getResult {
List<GetTraders> traders=new ArrayList<GetTraders>();
public void valueGivenByuser(String legal,String business,Object status)throws Exception {
GetTraders trade=new GetTraders(legal,business,status);
traders.add(trade); //Adding value to arrayList
}
}
The problem here is, once I added all values in traders arraylist I need to sort and display as output. I tried with collections.sort() but It shows compiler exception.
If you look closely to the Collections API, you will see that you have two options at your disposal:
1) make your GetTraders class implement the Comparable interface and call
public static <T extends Comparable<? super T>> void sort(List<T> list)
2) create a new Comparator for the GetTraders class and call
public static <T> void sort(List<T> list, Comparator<? super T> c)
The first solution is the easiest one but if you need to sort the GetTraders objects according to multiple criteria then the second one is the best choice.
As pointed out by #Vaseph, if you are using Java 8 instead, life suddenly becomes easier because all you need to do is:
traders.sort((GetTraders trade1, GetTraders trade2) -> {
return trade1.getBusinessName().compareTo(trade2.getBusinessName());
});
But if you are having troubles with the Comparable and Comparator interfaces, I would encourage you to first try the pre-Java-8 solutions before diving into the magic world of the functional interfaces.
For the sake of completeness, please also find below an example of each solution:
1) Comparable-based solution:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class GetTraders1 implements Comparable<GetTraders1> {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders1(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
#Override
public int compareTo(GetTraders1 that) {
return this.getTraderLegalName.compareTo(that.getTraderLegalName);
}
#Override
public String toString() {
return "GetTraders [getTraderLegalName=" + getTraderLegalName + ", businessName=" + businessName + ", status=" + status + "]";
}
public static void main(String[] args) {
GetTraders1 getTraders1 = new GetTraders1("1", "bn", "status");
GetTraders1 getTraders2 = new GetTraders1("2", "bn", "status");
GetTraders1 getTraders3 = new GetTraders1("3", "bn", "status");
List<GetTraders1> list = new ArrayList<>();
list.add(getTraders3);
list.add(getTraders2);
list.add(getTraders1);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
2) Comparator-based solution
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GetTraders2 {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders2(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
#Override
public String toString() {
return "GetTraders [getTraderLegalName=" + getTraderLegalName + ", businessName=" + businessName + ", status=" + status + "]";
}
public static void main(String[] args) {
GetTraders2 getTraders1 = new GetTraders2("1", "bn", "status");
GetTraders2 getTraders2 = new GetTraders2("2", "bn", "status");
GetTraders2 getTraders3 = new GetTraders2("3", "bn", "status");
List<GetTraders2> list = new ArrayList<>();
list.add(getTraders3);
list.add(getTraders2);
list.add(getTraders1);
System.out.println(list);
Collections.sort(list, new Comparator<GetTraders2>() {
#Override
public int compare(GetTraders2 o1, GetTraders2 o2) {
return o1.getTraderLegalName.compareTo(o2.getTraderLegalName);
}
});
System.out.println(list);
}
}
here is another way to sort list elements based on businessName:
traders.sort((GetTraders trade1, GetTraders trade2) -> {
return trade1.getBusinessName().compareTo(trade2.getBusinessName());
});
This hasn't be proposed but here it is.
You should use Collections#sort with a Comparator
Collections.sort(traders, (x, y) -> x.getXXX().compareTo(y.getXXX()));
// XXX could be any String object's getter
Use Comparator to determine order.
Collections.sort(someList, comparator);
How to get first element that matches a criteria in a stream? I've tried this but doesn't work
this.stops.stream().filter(Stop s-> s.getStation().getName().equals(name));
That criteria is not working, the filter method is invoked in an other class than Stop.
public class Train {
private final String name;
private final SortedSet<Stop> stops;
public Train(String name) {
this.name = name;
this.stops = new TreeSet<Stop>();
}
public void addStop(Stop stop) {
this.stops.add(stop);
}
public Stop getFirstStation() {
return this.getStops().first();
}
public Stop getLastStation() {
return this.getStops().last();
}
public SortedSet<Stop> getStops() {
return stops;
}
public SortedSet<Stop> getStopsAfter(String name) {
// return this.stops.subSet(, toElement);
return null;
}
}
import java.util.ArrayList;
import java.util.List;
public class Station {
private final String name;
private final List<Stop> stops;
public Station(String name) {
this.name = name;
this.stops = new ArrayList<Stop>();
}
public String getName() {
return name;
}
}
This might be what you are looking for:
yourStream
.filter(/* your criteria */)
.findFirst()
.get();
And better, if there's a possibility of matching no element, in which case get() will throw a NPE. So use:
yourStream
.filter(/* your criteria */)
.findFirst()
.orElse(null); /* You could also create a default object here */
An example:
public static void main(String[] args) {
class Stop {
private final String stationName;
private final int passengerCount;
Stop(final String stationName, final int passengerCount) {
this.stationName = stationName;
this.passengerCount = passengerCount;
}
}
List<Stop> stops = new LinkedList<>();
stops.add(new Stop("Station1", 250));
stops.add(new Stop("Station2", 275));
stops.add(new Stop("Station3", 390));
stops.add(new Stop("Station2", 210));
stops.add(new Stop("Station1", 190));
Stop firstStopAtStation1 = stops.stream()
.filter(e -> e.stationName.equals("Station1"))
.findFirst()
.orElse(null);
System.out.printf("At the first stop at Station1 there were %d passengers in the train.", firstStopAtStation1.passengerCount);
}
Output is:
At the first stop at Station1 there were 250 passengers in the train.
When you write a lambda expression, the argument list to the left of -> can be either a parenthesized argument list (possibly empty), or a single identifier without any parentheses. But in the second form, the identifier cannot be declared with a type name. Thus:
this.stops.stream().filter(Stop s-> s.getStation().getName().equals(name));
is incorrect syntax; but
this.stops.stream().filter((Stop s)-> s.getStation().getName().equals(name));
is correct. Or:
this.stops.stream().filter(s -> s.getStation().getName().equals(name));
is also correct if the compiler has enough information to figure out the types.
I think this is the best way:
this.stops.stream().filter(s -> Objects.equals(s.getStation().getName(), this.name)).findFirst().orElse(null);