Java 8에서 여러 필드 이름으로 그룹화
POJO에서 오브젝트를 필드명으로 그룹화하는 코드를 찾았습니다.그 코드는 다음과 같습니다.
public class Temp {
static class Person {
private String name;
private int age;
private long salary;
Person(String name, int age, long salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, salary=%d}", name, age, salary);
}
}
public static void main(String[] args) {
Stream<Person> people = Stream.of(new Person("Paul", 24, 20000),
new Person("Mark", 30, 30000),
new Person("Will", 28, 28000),
new Person("William", 28, 28000));
Map<Integer, List<Person>> peopleByAge;
peopleByAge = people
.collect(Collectors.groupingBy(p -> p.age, Collectors.mapping((Person p) -> p, toList())));
System.out.println(peopleByAge);
}
}
출력은 다음과 같습니다(정답).
{24=[Person{name='Paul', age=24, salary=20000}], 28=[Person{name='Will', age=28, salary=28000}, Person{name='William', age=28, salary=28000}], 30=[Person{name='Mark', age=30, salary=30000}]}
그러나 여러 필드를 기준으로 그룹화하려면 어떻게 해야 합니까?POJO를 넘겨줄 수 있어요groupingBy()
실시 후의 방법equals()
이 POJO에서 여러 필드를 기준으로 그룹화할 수 있는 다른 옵션이 있습니까?
예: 제 경우 이름과 나이에 따라 그룹화하고 싶습니다.
여기에는 몇 가지 옵션이 있습니다.가장 간단한 방법은 컬렉터를 연결하는 것입니다.
Map<String, Map<Integer, List<Person>>> map = people
.collect(Collectors.groupingBy(Person::getName,
Collectors.groupingBy(Person::getAge));
프레드로 불리는 18세 사람들의 목록을 얻으려면 다음을 이용해야 합니다.
map.get("Fred").get(18);
두 번째 옵션은 그룹을 나타내는 클래스를 정의하는 것입니다.사용자 내부에 있을 수 있습니다.이 코드에는record
하지만 그것은 쉽게 수업할 수 있다.equals
그리고.hashCode
JEP 359가 추가되기 전의 Java 버전에서는 다음과 같이 정의되어 있습니다.
class Person {
record NameAge(String name, int age) { }
public NameAge getNameAge() {
return new NameAge(name, age);
}
}
다음으로 다음을 사용할 수 있습니다.
Map<NameAge, List<Person>> map = people.collect(Collectors.groupingBy(Person::getNameAge));
를 사용하여 검색하다
map.get(new NameAge("Fred", 18));
마지막으로, 자신의 그룹 레코드를 구현하고 싶지 않은 경우 주변에 있는 Java 프레임워크의 대부분은pair
이런 종류의 것을 위해 만들어진 수업입니다.예: apache commons pair 다음 라이브러리 중 하나를 사용하면 맵의 키를 이름과 사용 기간의 쌍으로 만들 수 있습니다.
Map<Pair<String, Integer>, List<Person>> map =
people.collect(Collectors.groupingBy(p -> Pair.of(p.getName(), p.getAge())));
취득 방법:
map.get(Pair.of("Fred", 18));
개인적으로는 레코드가 언어로 제공되기 때문에 일반 튜플에 큰 가치를 느끼지 못합니다. 레코드는 의도를 더 잘 표시하고 코드를 거의 필요로 하지 않기 때문입니다.
여기 코드를 보세요.
기능성 스타일을 만들기만 하면 됩니다.
Function<Person, List<Object>> compositeKey = personRecord ->
Arrays.<Object>asList(personRecord.getName(), personRecord.getAge());
이제 맵으로 사용할 수 있습니다.
Map<Object, List<Person>> map =
people.collect(Collectors.groupingBy(compositeKey, Collectors.toList()));
건배!
안녕하세요. 간단히 연결하면groupingByKey
예를 들어
Map<String, List<Person>> peopleBySomeKey = people
.collect(Collectors.groupingBy(p -> getGroupingByKey(p), Collectors.mapping((Person p) -> p, toList())));
//write getGroupingByKey() function
private String getGroupingByKey(Person p){
return p.getAge()+"-"+p.getName();
}
List를 여러 필드의 분류자로 사용할 수 있지만 늘 값을 Optional로 랩해야 합니다.
Function<Item, List> classifier = (item) -> List.of(
item.getFieldA(),
item.getFieldB(),
Optional.ofNullable(item.getFieldC())
);
Map<List, List<Item>> grouped = items.stream()
.collect(Collectors.groupingBy(classifier));
그groupingBy
메서드의 첫 번째 매개 변수는 다음과 같습니다.Function<T,K>
여기서:
@parames(@parames)
<T>
입력 요소의 유형@parames(@parames)
<K>
열쇠의 종류
lamda를 코드의 익명 클래스로 대체하면 다음과 같은 것을 알 수 있습니다.
people.stream().collect(Collectors.groupingBy(new Function<Person, int>() {
@Override
public int apply(Person person) {
return person.getAge();
}
}));
방금 출력 매개 변수 변경<K>
예를 들어 이 경우 org.apache.commons.lang3의 페어 클래스를 사용했습니다.이름 및 연령별로 그룹화할 수 있는 튜플이지만 필요에 따라 그룹을 필터링할 수 있는 클래스를 만들 수 있습니다.
people.stream().collect(Collectors.groupingBy(new Function<Person, Pair<Integer, String>>() {
@Override
public YourFilter apply(Person person) {
return Pair.of(person.getAge(), person.getName());
}
}));
마지막으로 lamda back으로 대체한 후 코드는 다음과 같습니다.
Map<Pair<Integer,String>, List<Person>> peopleByAgeAndName = people.collect(Collectors.groupingBy(p -> Pair.of(person.getAge(), person.getName()), Collectors.mapping((Person p) -> p, toList())));
그룹의 키 정의에 대한 클래스를 정의합니다.
class KeyObj {
ArrayList<Object> keys;
public KeyObj( Object... objs ) {
keys = new ArrayList<Object>();
for (int i = 0; i < objs.length; i++) {
keys.add( objs[i] );
}
}
// Add appropriate isEqual() ... you IDE should generate this
}
이제 당신의 코드로,
peopleByManyParams = people
.collect(Collectors.groupingBy(p -> new KeyObj( p.age, p.other1, p.other2 ), Collectors.mapping((Person p) -> p, toList())));
나는 다양한 고객에게 점심을 제공하는 급식 회사에 보고해야 했다.다시 말해, 케이터링은 케이터링으로부터 주문을 받는 회사 또는 그 이상의 회사가 있을 수 있으며, 모든 고객을 위해 매일 얼마나 많은 점심을 생산해야 하는지 알아야 한다!
참고로 저는 이 예를 너무 복잡하게 만들지 않기 위해 정렬을 사용하지 않았습니다.
제 코드는 다음과 같습니다.
@Test
public void test_2() throws Exception {
Firm catering = DS.firm().get(1);
LocalDateTime ldtFrom = LocalDateTime.of(2017, Month.JANUARY, 1, 0, 0);
LocalDateTime ldtTo = LocalDateTime.of(2017, Month.MAY, 2, 0, 0);
Date dFrom = Date.from(ldtFrom.atZone(ZoneId.systemDefault()).toInstant());
Date dTo = Date.from(ldtTo.atZone(ZoneId.systemDefault()).toInstant());
List<PersonOrders> LON = DS.firm().getAllOrders(catering, dFrom, dTo, false);
Map<Object, Long> M = LON.stream().collect(
Collectors.groupingBy(p
-> Arrays.asList(p.getDatum(), p.getPerson().getIdfirm(), p.getIdProduct()),
Collectors.counting()));
for (Map.Entry<Object, Long> e : M.entrySet()) {
Object key = e.getKey();
Long value = e.getValue();
System.err.println(String.format("Client firm :%s, total: %d", key, value));
}
}
이것은 branchCode와 prdId를 여러 필드로 그룹화하여 필요한 사람을 위해 게시하는 방법입니다.
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
* @author charudatta.joshi
*/
public class Product1 {
public BigInteger branchCode;
public BigInteger prdId;
public String accountCode;
public BigDecimal actualBalance;
public BigDecimal sumActBal;
public BigInteger countOfAccts;
public Product1() {
}
public Product1(BigInteger branchCode, BigInteger prdId, String accountCode, BigDecimal actualBalance) {
this.branchCode = branchCode;
this.prdId = prdId;
this.accountCode = accountCode;
this.actualBalance = actualBalance;
}
public BigInteger getCountOfAccts() {
return countOfAccts;
}
public void setCountOfAccts(BigInteger countOfAccts) {
this.countOfAccts = countOfAccts;
}
public BigDecimal getSumActBal() {
return sumActBal;
}
public void setSumActBal(BigDecimal sumActBal) {
this.sumActBal = sumActBal;
}
public BigInteger getBranchCode() {
return branchCode;
}
public void setBranchCode(BigInteger branchCode) {
this.branchCode = branchCode;
}
public BigInteger getPrdId() {
return prdId;
}
public void setPrdId(BigInteger prdId) {
this.prdId = prdId;
}
public String getAccountCode() {
return accountCode;
}
public void setAccountCode(String accountCode) {
this.accountCode = accountCode;
}
public BigDecimal getActualBalance() {
return actualBalance;
}
public void setActualBalance(BigDecimal actualBalance) {
this.actualBalance = actualBalance;
}
@Override
public String toString() {
return "Product{" + "branchCode:" + branchCode + ", prdId:" + prdId + ", accountCode:" + accountCode + ", actualBalance:" + actualBalance + ", sumActBal:" + sumActBal + ", countOfAccts:" + countOfAccts + '}';
}
public static void main(String[] args) {
List<Product1> al = new ArrayList<Product1>();
System.out.println(al);
al.add(new Product1(new BigInteger("01"), new BigInteger("11"), "001", new BigDecimal("10")));
al.add(new Product1(new BigInteger("01"), new BigInteger("11"), "002", new BigDecimal("10")));
al.add(new Product1(new BigInteger("01"), new BigInteger("12"), "003", new BigDecimal("10")));
al.add(new Product1(new BigInteger("01"), new BigInteger("12"), "004", new BigDecimal("10")));
al.add(new Product1(new BigInteger("01"), new BigInteger("12"), "005", new BigDecimal("10")));
al.add(new Product1(new BigInteger("01"), new BigInteger("13"), "006", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("11"), "007", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("11"), "008", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("12"), "009", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("12"), "010", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("12"), "011", new BigDecimal("10")));
al.add(new Product1(new BigInteger("02"), new BigInteger("13"), "012", new BigDecimal("10")));
//Map<BigInteger, Long> counting = al.stream().collect(Collectors.groupingBy(Product1::getBranchCode, Collectors.counting()));
// System.out.println(counting);
//group by branch code
Map<BigInteger, List<Product1>> groupByBrCd = al.stream().collect(Collectors.groupingBy(Product1::getBranchCode, Collectors.toList()));
System.out.println("\n\n\n" + groupByBrCd);
Map<BigInteger, List<Product1>> groupByPrId = null;
// Create a final List to show for output containing one element of each group
List<Product> finalOutputList = new LinkedList<Product>();
Product newPrd = null;
// Iterate over resultant Map Of List
Iterator<BigInteger> brItr = groupByBrCd.keySet().iterator();
Iterator<BigInteger> prdidItr = null;
BigInteger brCode = null;
BigInteger prdId = null;
Map<BigInteger, List<Product>> tempMap = null;
List<Product1> accListPerBr = null;
List<Product1> accListPerBrPerPrd = null;
Product1 tempPrd = null;
Double sum = null;
while (brItr.hasNext()) {
brCode = brItr.next();
//get list per branch
accListPerBr = groupByBrCd.get(brCode);
// group by br wise product wise
groupByPrId=accListPerBr.stream().collect(Collectors.groupingBy(Product1::getPrdId, Collectors.toList()));
System.out.println("====================");
System.out.println(groupByPrId);
prdidItr = groupByPrId.keySet().iterator();
while(prdidItr.hasNext()){
prdId=prdidItr.next();
// get list per brcode+product code
accListPerBrPerPrd=groupByPrId.get(prdId);
newPrd = new Product();
// Extract zeroth element to put in Output List to represent this group
tempPrd = accListPerBrPerPrd.get(0);
newPrd.setBranchCode(tempPrd.getBranchCode());
newPrd.setPrdId(tempPrd.getPrdId());
//Set accCOunt by using size of list of our group
newPrd.setCountOfAccts(BigInteger.valueOf(accListPerBrPerPrd.size()));
//Sum actual balance of our of list of our group
sum = accListPerBrPerPrd.stream().filter(o -> o.getActualBalance() != null).mapToDouble(o -> o.getActualBalance().doubleValue()).sum();
newPrd.setSumActBal(BigDecimal.valueOf(sum));
// Add product element in final output list
finalOutputList.add(newPrd);
}
}
System.out.println("+++++++++++++++++++++++");
System.out.println(finalOutputList);
}
}
출력은 다음과 같습니다.
+++++++++++++++++++++++
[Product{branchCode:1, prdId:11, accountCode:null, actualBalance:null, sumActBal:20.0, countOfAccts:2}, Product{branchCode:1, prdId:12, accountCode:null, actualBalance:null, sumActBal:30.0, countOfAccts:3}, Product{branchCode:1, prdId:13, accountCode:null, actualBalance:null, sumActBal:10.0, countOfAccts:1}, Product{branchCode:2, prdId:11, accountCode:null, actualBalance:null, sumActBal:20.0, countOfAccts:2}, Product{branchCode:2, prdId:12, accountCode:null, actualBalance:null, sumActBal:30.0, countOfAccts:3}, Product{branchCode:2, prdId:13, accountCode:null, actualBalance:null, sumActBal:10.0, countOfAccts:1}]
포맷 후:
[
Product{branchCode:1, prdId:11, accountCode:null, actualBalance:null, sumActBal:20.0, countOfAccts:2},
Product{branchCode:1, prdId:12, accountCode:null, actualBalance:null, sumActBal:30.0, countOfAccts:3},
Product{branchCode:1, prdId:13, accountCode:null, actualBalance:null, sumActBal:10.0, countOfAccts:1},
Product{branchCode:2, prdId:11, accountCode:null, actualBalance:null, sumActBal:20.0, countOfAccts:2},
Product{branchCode:2, prdId:12, accountCode:null, actualBalance:null, sumActBal:30.0, countOfAccts:3},
Product{branchCode:2, prdId:13, accountCode:null, actualBalance:null, sumActBal:10.0, countOfAccts:1}
]
언급URL : https://stackoverflow.com/questions/28342814/group-by-multiple-field-names-in-java-8
'programing' 카테고리의 다른 글
MySQL: GROUP_CONCAT 값 정렬 (0) | 2022.09.27 |
---|---|
php 스크립트에서 ssh를 통해 가상 시스템의 mariadb에 연결하지 못함 (0) | 2022.09.27 |
테이블의 행을 업데이트하거나 존재하지 않는 경우 삽입하려면 어떻게 해야 합니까? (0) | 2022.09.27 |
VARB란INALY(MAX)는? (0) | 2022.09.27 |
System.gc()는 언제 어떤 처리를 합니까? (0) | 2022.09.27 |